]>
Commit | Line | Data |
---|---|---|
2fac6a6c | 1 | /* Check for GLOB_TIDLE heap allocation issues (bugs 22320, 22325, 22332). |
04277e02 | 2 | Copyright (C) 2017-2019 Free Software Foundation, Inc. |
e80fc1fc FW |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <glob.h> | |
20 | #include <mcheck.h> | |
21 | #include <nss.h> | |
22 | #include <pwd.h> | |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | #include <support/check.h> | |
26 | #include <support/support.h> | |
27 | ||
28 | /* Flag which indicates whether to pass the GLOB_ONLYDIR flag. */ | |
29 | static int do_onlydir; | |
30 | ||
31 | /* Flag which indicates whether to pass the GLOB_NOCHECK flag. */ | |
32 | static int do_nocheck; | |
33 | ||
34 | /* Flag which indicates whether to pass the GLOB_MARK flag. */ | |
35 | static int do_mark; | |
36 | ||
2fac6a6c FW |
37 | /* Flag which indicates whether to pass the GLOB_NOESCAPE flag. */ |
38 | static int do_noescape; | |
39 | ||
e80fc1fc FW |
40 | static void |
41 | one_test (const char *prefix, const char *middle, const char *suffix) | |
42 | { | |
43 | char *pattern = xasprintf ("%s%s%s", prefix, middle, suffix); | |
44 | int flags = GLOB_TILDE; | |
45 | if (do_onlydir) | |
46 | flags |= GLOB_ONLYDIR; | |
47 | if (do_nocheck) | |
48 | flags |= GLOB_NOCHECK; | |
49 | if (do_mark) | |
50 | flags |= GLOB_MARK; | |
2fac6a6c FW |
51 | if (do_noescape) |
52 | flags |= GLOB_NOESCAPE; | |
e80fc1fc FW |
53 | glob_t gl; |
54 | /* This glob call might result in crashes or memory leaks. */ | |
55 | if (glob (pattern, flags, NULL, &gl) == 0) | |
56 | globfree (&gl); | |
57 | free (pattern); | |
58 | } | |
59 | ||
60 | enum | |
61 | { | |
62 | /* The largest base being tested. */ | |
63 | largest_base_size = 500000, | |
64 | ||
65 | /* The actual size is the base size plus a variable whose absolute | |
66 | value is not greater than this. This helps malloc to trigger | |
67 | overflows. */ | |
68 | max_size_skew = 16, | |
69 | ||
70 | /* The maximum string length supported by repeating_string | |
71 | below. */ | |
72 | repeat_size = largest_base_size + max_size_skew, | |
73 | }; | |
74 | ||
75 | /* Used to construct strings which repeat a single character 'x'. */ | |
76 | static char *repeat; | |
77 | ||
78 | /* Return a string of SIZE characters. */ | |
79 | const char * | |
80 | repeating_string (int size) | |
81 | { | |
82 | TEST_VERIFY (size >= 0); | |
83 | TEST_VERIFY (size <= repeat_size); | |
84 | const char *repeated_shifted = repeat + repeat_size - size; | |
85 | TEST_VERIFY (strlen (repeated_shifted) == size); | |
86 | return repeated_shifted; | |
87 | } | |
88 | ||
89 | static int | |
90 | do_test (void) | |
91 | { | |
92 | /* Avoid network-based NSS modules and initialize nss_files with a | |
93 | dummy lookup. This has to come before mtrace because NSS does | |
94 | not free all memory. */ | |
95 | __nss_configure_lookup ("passwd", "files"); | |
96 | (void) getpwnam ("root"); | |
97 | ||
98 | mtrace (); | |
99 | ||
100 | repeat = xmalloc (repeat_size + 1); | |
101 | memset (repeat, 'x', repeat_size); | |
102 | repeat[repeat_size] = '\0'; | |
103 | ||
104 | /* These numbers control the size of the user name. The values | |
105 | cover the minimum (0), a typical size (8), a large | |
106 | stack-allocated size (100000), and a somewhat large | |
107 | heap-allocated size (largest_base_size). */ | |
108 | static const int base_sizes[] = { 0, 8, 100, 100000, largest_base_size, -1 }; | |
109 | ||
110 | for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir) | |
111 | for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck) | |
112 | for (do_mark = 0; do_mark < 2; ++do_mark) | |
2fac6a6c FW |
113 | for (do_noescape = 0; do_noescape < 2; ++do_noescape) |
114 | for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx) | |
115 | { | |
116 | for (int size_skew = -max_size_skew; size_skew <= max_size_skew; | |
117 | ++size_skew) | |
118 | { | |
119 | int size = base_sizes[base_idx] + size_skew; | |
120 | if (size < 0) | |
121 | continue; | |
122 | ||
123 | const char *user_name = repeating_string (size); | |
124 | one_test ("~", user_name, "/a/b"); | |
125 | one_test ("~", user_name, "x\\x\\x////x\\a"); | |
126 | } | |
127 | ||
128 | const char *user_name = repeating_string (base_sizes[base_idx]); | |
129 | one_test ("~", user_name, ""); | |
130 | one_test ("~", user_name, "/"); | |
131 | one_test ("~", user_name, "/a"); | |
132 | one_test ("~", user_name, "/*/*"); | |
133 | one_test ("~", user_name, "\\/"); | |
134 | one_test ("/~", user_name, ""); | |
135 | one_test ("*/~", user_name, "/a/b"); | |
136 | } | |
e80fc1fc FW |
137 | |
138 | free (repeat); | |
139 | ||
140 | return 0; | |
141 | } | |
142 | ||
ba374b6d | 143 | #define TIMEOUT 200 |
e80fc1fc | 144 | #include <support/test-driver.c> |