1
0
mirror of https://git.savannah.gnu.org/git/gnulib.git synced 2025-08-17 12:41:05 +03:00

getcwd: break fdopendir + save_cwd recursive loop (Bug#13516)

Reported for OS X 10.8.2 by Assaf Gordon in
<http://bugs.gnu.org/13516>.
* lib/getcwd.c (HAVE_OPENAT_SUPPORT): Do not define if
!HAVE_OPENAT && !HAVE_FDOPENDIR.
* m4/getcwd-abort-bug.m4: Reformat to match test-getcwd.c
so that they can be kept in sync more easily.  Avoid PATH_MAX
test on the Hurd.  Sync from test-getcwd.c for errno tests after
mkdir or chdir failure.
* tests/test-getcwd.c (HAVE_OPENAT_SUPPORT): New macro, from
lib/getcwd.c.
(test_abort_bug): Do not test for the deep directory bug unless we
have openat support.  Avoid PATH_MAX test on the Hurd.
This commit is contained in:
Paul Eggert
2013-02-03 21:28:30 -08:00
parent 6668cfa30c
commit ca369c8d66
4 changed files with 99 additions and 62 deletions

View File

@@ -1,5 +1,19 @@
2013-02-03 Paul Eggert <eggert@cs.ucla.edu> 2013-02-03 Paul Eggert <eggert@cs.ucla.edu>
getcwd: break fdopendir + save_cwd recursive loop (Bug#13516)
Reported for OS X 10.8.2 by Assaf Gordon in
<http://bugs.gnu.org/13516>.
* lib/getcwd.c (HAVE_OPENAT_SUPPORT): Do not define if
!HAVE_OPENAT && !HAVE_FDOPENDIR.
* m4/getcwd-abort-bug.m4: Reformat to match test-getcwd.c
so that they can be kept in sync more easily. Avoid PATH_MAX
test on the Hurd. Sync from test-getcwd.c for errno tests after
mkdir or chdir failure.
* tests/test-getcwd.c (HAVE_OPENAT_SUPPORT): New macro, from
lib/getcwd.c.
(test_abort_bug): Do not test for the deep directory bug unless we
have openat support. Avoid PATH_MAX test on the Hurd.
regex-tests, regex: fix bug: memset undeclared regex-tests, regex: fix bug: memset undeclared
* tests/test-regex.c: Don't include regex.h twice. Include * tests/test-regex.c: Don't include regex.h twice. Include
string.h, to declare memset. Christensen's report also mentioned string.h, to declare memset. Christensen's report also mentioned

View File

@@ -28,9 +28,9 @@
#include <fcntl.h> /* For AT_FDCWD on Solaris 9. */ #include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
/* If this host provides the openat function or if we're using the /* If this host provides the openat function or if we're using the
gnulib replacement function, then enable code below to make getcwd gnulib replacement function with a native fdopendir, then enable
more efficient and robust. */ code below to make getcwd more efficient and robust. */
#if defined HAVE_OPENAT || defined GNULIB_OPENAT #if defined HAVE_OPENAT || (defined GNULIB_OPENAT && defined HAVE_FDOPENDIR)
# define HAVE_OPENAT_SUPPORT 1 # define HAVE_OPENAT_SUPPORT 1
#else #else
# define HAVE_OPENAT_SUPPORT 0 # define HAVE_OPENAT_SUPPORT 0

View File

@@ -58,16 +58,18 @@ AC_DEFUN([gl_FUNC_GETCWD_ABORT_BUG],
int int
main () main ()
{ {
char const *dir_name = "confdir-14B---";
char *cwd; char *cwd;
size_t initial_cwd_len; size_t initial_cwd_len;
int fail = 0; int fail = 0;
size_t desired_depth;
size_t d;
/* The bug is triggered when PATH_MAX < getpagesize (), so skip /* The bug is triggered when PATH_MAX < getpagesize (), so skip
this relatively expensive and invasive test if that's not true. */ this relatively expensive and invasive test if that's not true. */
if (getpagesize () <= PATH_MAX) #ifdef PATH_MAX
int bug_possible = PATH_MAX < getpagesize ();
#else
int bug_possible = 0;
#endif
if (! bug_possible)
return 0; return 0;
cwd = getcwd (NULL, 0); cwd = getcwd (NULL, 0);
@@ -76,35 +78,43 @@ main ()
initial_cwd_len = strlen (cwd); initial_cwd_len = strlen (cwd);
free (cwd); free (cwd);
desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
/ (1 + strlen (dir_name)));
for (d = 0; d < desired_depth; d++)
{
if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
{
fail = 3; /* Unable to construct deep hierarchy. */
break;
}
}
/* If libc has the bug in question, this invocation of getcwd if (1)
results in a failed assertion. */
cwd = getcwd (NULL, 0);
if (cwd == NULL)
fail = 4; /* getcwd failed: it refuses to return a string longer
than PATH_MAX. */
free (cwd);
/* Call rmdir first, in case the above chdir failed. */
rmdir (dir_name);
while (0 < d--)
{ {
if (chdir ("..") < 0) static char const dir_name[] = "confdir-14B---";
size_t desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
/ sizeof dir_name);
size_t d;
for (d = 0; d < desired_depth; d++)
{ {
fail = 5; if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
break; {
if (! (errno == ERANGE || errno == ENAMETOOLONG
|| errno == ENOENT))
fail = 3; /* Unable to construct deep hierarchy. */
break;
}
} }
/* If libc has the bug in question, this invocation of getcwd
results in a failed assertion. */
cwd = getcwd (NULL, 0);
if (cwd == NULL)
fail = 4; /* getcwd didn't assert, but it failed for a long name
where the answer could have been learned. */
free (cwd);
/* Call rmdir first, in case the above chdir failed. */
rmdir (dir_name); rmdir (dir_name);
while (0 < d--)
{
if (chdir ("..") < 0)
{
fail = 5;
break;
}
rmdir (dir_name);
}
} }
return fail; return fail;

View File

@@ -38,23 +38,29 @@
trigger a bug in glibc's getcwd implementation before 2.4.90-10. */ trigger a bug in glibc's getcwd implementation before 2.4.90-10. */
#define TARGET_LEN (5 * 1024) #define TARGET_LEN (5 * 1024)
#if defined HAVE_OPENAT || (defined GNULIB_OPENAT && defined HAVE_FDOPENDIR)
# define HAVE_OPENAT_SUPPORT 1
#else
# define HAVE_OPENAT_SUPPORT 0
#endif
/* Keep this test in sync with m4/getcwd-abort-bug.m4. */ /* Keep this test in sync with m4/getcwd-abort-bug.m4. */
static int static int
test_abort_bug (void) test_abort_bug (void)
{ {
char const *dir_name = "confdir-14B---";
char *cwd; char *cwd;
size_t initial_cwd_len; size_t initial_cwd_len;
int fail = 0; int fail = 0;
size_t desired_depth;
size_t d;
#ifdef PATH_MAX
/* The bug is triggered when PATH_MAX < getpagesize (), so skip /* The bug is triggered when PATH_MAX < getpagesize (), so skip
this relatively expensive and invasive test if that's not true. */ this relatively expensive and invasive test if that's not true. */
if (getpagesize () <= PATH_MAX) #ifdef PATH_MAX
return 0; int bug_possible = PATH_MAX < getpagesize ();
#else
int bug_possible = 0;
#endif #endif
if (! bug_possible)
return 0;
cwd = getcwd (NULL, 0); cwd = getcwd (NULL, 0);
if (cwd == NULL) if (cwd == NULL)
@@ -62,36 +68,43 @@ test_abort_bug (void)
initial_cwd_len = strlen (cwd); initial_cwd_len = strlen (cwd);
free (cwd); free (cwd);
desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
/ (1 + strlen (dir_name)));
for (d = 0; d < desired_depth; d++)
{
if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
{
if (! (errno == ERANGE || errno == ENAMETOOLONG || errno == ENOENT))
fail = 3; /* Unable to construct deep hierarchy. */
break;
}
}
/* If libc has the bug in question, this invocation of getcwd if (HAVE_OPENAT_SUPPORT)
results in a failed assertion. */
cwd = getcwd (NULL, 0);
if (cwd == NULL)
fail = 4; /* getcwd didn't assert, but it failed for a long name
where the answer could have been learned. */
free (cwd);
/* Call rmdir first, in case the above chdir failed. */
rmdir (dir_name);
while (0 < d--)
{ {
if (chdir ("..") < 0) static char const dir_name[] = "confdir-14B---";
size_t desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
/ sizeof dir_name);
size_t d;
for (d = 0; d < desired_depth; d++)
{ {
fail = 5; if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
break; {
if (! (errno == ERANGE || errno == ENAMETOOLONG
|| errno == ENOENT))
fail = 3; /* Unable to construct deep hierarchy. */
break;
}
} }
/* If libc has the bug in question, this invocation of getcwd
results in a failed assertion. */
cwd = getcwd (NULL, 0);
if (cwd == NULL)
fail = 4; /* getcwd didn't assert, but it failed for a long name
where the answer could have been learned. */
free (cwd);
/* Call rmdir first, in case the above chdir failed. */
rmdir (dir_name); rmdir (dir_name);
while (0 < d--)
{
if (chdir ("..") < 0)
{
fail = 5;
break;
}
rmdir (dir_name);
}
} }
return fail; return fail;