Mercurial > gnulib
comparison tests/test-getcwd.c @ 17311:ab5135d5ff83
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.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Sun, 03 Feb 2013 21:28:30 -0800 |
parents | e542fd46ad6f |
children | 344018b6e5d7 |
comparison
equal
deleted
inserted
replaced
17310:a9f418d6d676 | 17311:ab5135d5ff83 |
---|---|
36 /* This size is chosen to be larger than PATH_MAX (4k), yet smaller than | 36 /* This size is chosen to be larger than PATH_MAX (4k), yet smaller than |
37 the 16kB pagesize on ia64 linux. Those conditions make the code below | 37 the 16kB pagesize on ia64 linux. Those conditions make the code below |
38 trigger a bug in glibc's getcwd implementation before 2.4.90-10. */ | 38 trigger a bug in glibc's getcwd implementation before 2.4.90-10. */ |
39 #define TARGET_LEN (5 * 1024) | 39 #define TARGET_LEN (5 * 1024) |
40 | 40 |
41 #if defined HAVE_OPENAT || (defined GNULIB_OPENAT && defined HAVE_FDOPENDIR) | |
42 # define HAVE_OPENAT_SUPPORT 1 | |
43 #else | |
44 # define HAVE_OPENAT_SUPPORT 0 | |
45 #endif | |
46 | |
41 /* Keep this test in sync with m4/getcwd-abort-bug.m4. */ | 47 /* Keep this test in sync with m4/getcwd-abort-bug.m4. */ |
42 static int | 48 static int |
43 test_abort_bug (void) | 49 test_abort_bug (void) |
44 { | 50 { |
45 char const *dir_name = "confdir-14B---"; | |
46 char *cwd; | 51 char *cwd; |
47 size_t initial_cwd_len; | 52 size_t initial_cwd_len; |
48 int fail = 0; | 53 int fail = 0; |
49 size_t desired_depth; | 54 |
50 size_t d; | |
51 | |
52 #ifdef PATH_MAX | |
53 /* The bug is triggered when PATH_MAX < getpagesize (), so skip | 55 /* The bug is triggered when PATH_MAX < getpagesize (), so skip |
54 this relatively expensive and invasive test if that's not true. */ | 56 this relatively expensive and invasive test if that's not true. */ |
55 if (getpagesize () <= PATH_MAX) | 57 #ifdef PATH_MAX |
58 int bug_possible = PATH_MAX < getpagesize (); | |
59 #else | |
60 int bug_possible = 0; | |
61 #endif | |
62 if (! bug_possible) | |
56 return 0; | 63 return 0; |
57 #endif | |
58 | 64 |
59 cwd = getcwd (NULL, 0); | 65 cwd = getcwd (NULL, 0); |
60 if (cwd == NULL) | 66 if (cwd == NULL) |
61 return 2; | 67 return 2; |
62 | 68 |
63 initial_cwd_len = strlen (cwd); | 69 initial_cwd_len = strlen (cwd); |
64 free (cwd); | 70 free (cwd); |
65 desired_depth = ((TARGET_LEN - 1 - initial_cwd_len) | 71 |
66 / (1 + strlen (dir_name))); | 72 if (HAVE_OPENAT_SUPPORT) |
67 for (d = 0; d < desired_depth; d++) | |
68 { | 73 { |
69 if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0) | 74 static char const dir_name[] = "confdir-14B---"; |
70 { | 75 size_t desired_depth = ((TARGET_LEN - 1 - initial_cwd_len) |
71 if (! (errno == ERANGE || errno == ENAMETOOLONG || errno == ENOENT)) | 76 / sizeof dir_name); |
72 fail = 3; /* Unable to construct deep hierarchy. */ | 77 size_t d; |
73 break; | 78 for (d = 0; d < desired_depth; d++) |
74 } | 79 { |
75 } | 80 if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0) |
76 | 81 { |
77 /* If libc has the bug in question, this invocation of getcwd | 82 if (! (errno == ERANGE || errno == ENAMETOOLONG |
78 results in a failed assertion. */ | 83 || errno == ENOENT)) |
79 cwd = getcwd (NULL, 0); | 84 fail = 3; /* Unable to construct deep hierarchy. */ |
80 if (cwd == NULL) | 85 break; |
81 fail = 4; /* getcwd didn't assert, but it failed for a long name | 86 } |
82 where the answer could have been learned. */ | 87 } |
83 free (cwd); | 88 |
84 | 89 /* If libc has the bug in question, this invocation of getcwd |
85 /* Call rmdir first, in case the above chdir failed. */ | 90 results in a failed assertion. */ |
86 rmdir (dir_name); | 91 cwd = getcwd (NULL, 0); |
87 while (0 < d--) | 92 if (cwd == NULL) |
88 { | 93 fail = 4; /* getcwd didn't assert, but it failed for a long name |
89 if (chdir ("..") < 0) | 94 where the answer could have been learned. */ |
90 { | 95 free (cwd); |
91 fail = 5; | 96 |
92 break; | 97 /* Call rmdir first, in case the above chdir failed. */ |
93 } | |
94 rmdir (dir_name); | 98 rmdir (dir_name); |
99 while (0 < d--) | |
100 { | |
101 if (chdir ("..") < 0) | |
102 { | |
103 fail = 5; | |
104 break; | |
105 } | |
106 rmdir (dir_name); | |
107 } | |
95 } | 108 } |
96 | 109 |
97 return fail; | 110 return fail; |
98 } | 111 } |
99 | 112 |