Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* Alignment/padding coverage test for string comparison.
2 Copyright (C) 2016-2019 Free Software Foundation, Inc.
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>
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29#include <libc-diag.h>
30
31static int
32signum (int val)
33{
34 if (val < 0)
35 return -1;
36 if (val > 0)
37 return 1;
38 else
39 return 0;
40}
41
42static size_t
43max_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
55static int
56strncmp_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
63static int
64strncasecmp_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
71static int
72strncmp_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
79static int
80strncasecmp_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
87static int
88strncmp_64 (const char *left, const char *right)
89{
90 return strncmp (left, right, 64);
91}
92
93static int
94strncasecmp_64 (const char *left, const char *right)
95{
96 return strncasecmp (left, right, 64);
97}
98
99static int
100strncmp_max (const char *left, const char *right)
101{
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
108 return strncmp (left, right, SIZE_MAX);
109 DIAG_POP_NEEDS_COMMENT;
110}
111
112static int
113strncasecmp_max (const char *left, const char *right)
114{
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
121 return strncasecmp (left, right, SIZE_MAX);
122 DIAG_POP_NEEDS_COMMENT;
123}
124
125int
126do_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. */
225#define TIMEOUT 600
226
227#include <support/test-driver.c>
228

Warning: That file was not part of the compilation database. It may have many parsing errors.