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:
14
ChangeLog
14
ChangeLog
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user