]>
Commit | Line | Data |
---|---|---|
6e263a27 | 1 | /* Alignment/padding coverage test for string comparison. |
688903eb | 2 | Copyright (C) 2016-2018 Free Software Foundation, Inc. |
6e263a27 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 | /* This performs test comparisons with various (mis)alignments and | |
20 | characters in the padding. It is partly a regression test for bug | |
21 | 20327. */ | |
22 | ||
23 | #include <limits.h> | |
24 | #include <malloc.h> | |
25 | #include <stdbool.h> | |
ceaa9889 | 26 | #include <stdint.h> |
6e263a27 FW |
27 | #include <stdlib.h> |
28 | #include <string.h> | |
99c7adf9 | 29 | #include <libc-diag.h> |
6e263a27 FW |
30 | |
31 | static int | |
32 | signum (int val) | |
33 | { | |
34 | if (val < 0) | |
35 | return -1; | |
36 | if (val > 0) | |
37 | return 1; | |
38 | else | |
39 | return 0; | |
40 | } | |
41 | ||
42 | static size_t | |
43 | max_size_t (size_t left, size_t right) | |
44 | { | |
45 | if (left > right) | |
46 | return left; | |
47 | else | |
48 | return right; | |
49 | } | |
50 | ||
51 | /* Wrappers for strncmp and strncasecmp which determine the maximum | |
52 | string length in some, either based on the input string length, or | |
53 | using fixed constants. */ | |
54 | ||
55 | static int | |
56 | strncmp_no_terminator (const char *left, const char *right) | |
57 | { | |
58 | size_t left_len = strlen (left); | |
59 | size_t right_len = strlen (right); | |
60 | return strncmp (left, right, max_size_t (left_len, right_len)); | |
61 | } | |
62 | ||
63 | static int | |
64 | strncasecmp_no_terminator (const char *left, const char *right) | |
65 | { | |
66 | size_t left_len = strlen (left); | |
67 | size_t right_len = strlen (right); | |
68 | return strncasecmp (left, right, max_size_t (left_len, right_len)); | |
69 | } | |
70 | ||
71 | static int | |
72 | strncmp_terminator (const char *left, const char *right) | |
73 | { | |
74 | size_t left_len = strlen (left); | |
75 | size_t right_len = strlen (right); | |
76 | return strncmp (left, right, max_size_t (left_len, right_len)); | |
77 | } | |
78 | ||
79 | static int | |
80 | strncasecmp_terminator (const char *left, const char *right) | |
81 | { | |
82 | size_t left_len = strlen (left); | |
83 | size_t right_len = strlen (right); | |
84 | return strncasecmp (left, right, max_size_t (left_len, right_len)); | |
85 | } | |
86 | ||
87 | static int | |
88 | strncmp_64 (const char *left, const char *right) | |
89 | { | |
90 | return strncmp (left, right, 64); | |
91 | } | |
92 | ||
93 | static int | |
94 | strncasecmp_64 (const char *left, const char *right) | |
95 | { | |
96 | return strncasecmp (left, right, 64); | |
97 | } | |
98 | ||
99 | static int | |
100 | strncmp_max (const char *left, const char *right) | |
101 | { | |
99c7adf9 JM |
102 | DIAG_PUSH_NEEDS_COMMENT; |
103 | #if __GNUC_PREREQ (7, 0) | |
104 | /* GCC 9 warns about the size passed to strncmp being larger than | |
105 | PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */ | |
106 | DIAG_IGNORE_NEEDS_COMMENT (9, "-Wstringop-overflow="); | |
107 | #endif | |
6e263a27 | 108 | return strncmp (left, right, SIZE_MAX); |
99c7adf9 | 109 | DIAG_POP_NEEDS_COMMENT; |
6e263a27 FW |
110 | } |
111 | ||
112 | static int | |
113 | strncasecmp_max (const char *left, const char *right) | |
114 | { | |
99c7adf9 JM |
115 | DIAG_PUSH_NEEDS_COMMENT; |
116 | #if __GNUC_PREREQ (7, 0) | |
117 | /* GCC 9 warns about the size passed to strncasecmp being larger | |
118 | than PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */ | |
119 | DIAG_IGNORE_NEEDS_COMMENT (9, "-Wstringop-overflow="); | |
120 | #endif | |
6e263a27 | 121 | return strncasecmp (left, right, SIZE_MAX); |
99c7adf9 | 122 | DIAG_POP_NEEDS_COMMENT; |
6e263a27 FW |
123 | } |
124 | ||
fb82116f | 125 | int |
6e263a27 FW |
126 | do_test (void) |
127 | { | |
128 | enum { | |
129 | max_align = 64, | |
130 | max_string_length = 33 | |
131 | }; | |
132 | size_t blob_size = max_align + max_string_length + 1; | |
133 | char *left = memalign (max_align, blob_size); | |
134 | char *right = memalign (max_align, blob_size); | |
135 | if (left == NULL || right == NULL) | |
136 | { | |
137 | printf ("error: out of memory\n"); | |
138 | return 1; | |
139 | } | |
140 | ||
141 | const struct | |
142 | { | |
143 | const char *name; | |
144 | int (*implementation) (const char *, const char *); | |
145 | } functions[] = | |
146 | { | |
147 | { "strcmp", strcmp }, | |
148 | { "strcasecmp", strcasecmp }, | |
149 | { "strncmp (without NUL)", strncmp_no_terminator}, | |
150 | { "strncasecmp (without NUL)", strncasecmp_no_terminator}, | |
151 | { "strncmp (with NUL)", strncmp_terminator}, | |
152 | { "strncasecmp (with NUL)", strncasecmp_terminator}, | |
153 | { "strncmp (length 64)", strncmp_64}, | |
154 | { "strncasecmp (length 64)", strncasecmp_64}, | |
155 | { "strncmp (length SIZE_MAX)", strncmp_max}, | |
156 | { "strncasecmp (length SIZE_MAX)", strncasecmp_max}, | |
157 | { NULL, NULL } | |
158 | }; | |
159 | const char *const strings[] = | |
160 | { | |
161 | "", | |
162 | "0", | |
163 | "01", | |
164 | "01234567", | |
165 | "0123456789abcde", | |
166 | "0123456789abcdef", | |
167 | "0123456789abcdefg", | |
168 | "1", | |
169 | "10", | |
170 | "123456789abcdef", | |
171 | "123456789abcdefg", | |
172 | "23456789abcdef", | |
173 | "23456789abcdefg", | |
174 | "abcdefghijklmnopqrstuvwxyzABCDEF", | |
175 | NULL | |
176 | }; | |
177 | const unsigned char pads[] = | |
178 | { 0, 1, 32, 64, 128, '0', '1', 'e', 'f', 'g', 127, 192, 255 }; | |
179 | ||
180 | bool errors = false; | |
181 | for (int left_idx = 0; strings[left_idx] != NULL; ++left_idx) | |
182 | for (int left_align = 0; left_align < max_align; ++left_align) | |
183 | for (unsigned pad_left = 0; pad_left < sizeof (pads); ++pad_left) | |
184 | { | |
185 | memset (left, pads[pad_left], blob_size); | |
186 | strcpy (left + left_align, strings[left_idx]); | |
187 | ||
188 | for (int right_idx = 0; strings[right_idx] != NULL; ++right_idx) | |
189 | for (unsigned pad_right = 0; pad_right < sizeof (pads); | |
190 | ++pad_right) | |
191 | for (int right_align = 0; right_align < max_align; | |
192 | ++right_align) | |
193 | { | |
194 | memset (right, pads[pad_right], blob_size); | |
195 | strcpy (right + right_align, strings[right_idx]); | |
196 | ||
197 | for (int func = 0; functions[func].name != NULL; ++func) | |
198 | { | |
199 | int expected = left_idx - right_idx; | |
200 | int actual = functions[func].implementation | |
201 | (left + left_align, right + right_align); | |
202 | if (signum (actual) != signum (expected)) | |
203 | { | |
204 | printf ("error: mismatch for %s: %d\n" | |
205 | " left: \"%s\"\n" | |
206 | " right: \"%s\"\n" | |
207 | " pad_left = %u, pad_right = %u,\n" | |
208 | " left_align = %d, right_align = %d\n", | |
209 | functions[func].name, actual, | |
210 | strings[left_idx], strings[right_idx], | |
211 | pad_left, pad_right, | |
212 | left_align, right_align); | |
213 | errors = true; | |
214 | } | |
215 | } | |
216 | } | |
217 | } | |
218 | free (right); | |
219 | free (left); | |
220 | return errors; | |
221 | } | |
222 | ||
223 | /* The nested loops need a long time to complete on slower | |
224 | machines. */ | |
3cefdd73 | 225 | #define TIMEOUT 600 |
6e263a27 | 226 | |
fb82116f | 227 | #include <support/test-driver.c> |