Refer to C23 in place of C2X in glibc
[glibc.git] / stdio-common / tst-sscanf.c
blob3cf656763e66bf4eb49be403db837ab0be52fd47
1 /* Copyright (C) 2000-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 #include <array_length.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <locale.h>
23 #ifndef CHAR
24 # define CHAR char
25 # define L(str) str
26 # define SSCANF sscanf
27 #endif
29 const CHAR *str_double[] =
31 L("-.10000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01"),
32 L("0.10000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01"),
33 L("-1234567E0198765432E0912345678901987654321091234567890198765432109"),
34 L("-0.1000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01")
37 const double val_double[] =
39 -.10000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01,
40 0.10000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01,
41 -1234567E01, 98765432E09, 12345678901.0, 98765432109.0, 12345678901.0,
42 98765432109.0,
43 -0.1000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01
46 const CHAR *str_long[] =
48 L("-12345678987654321123456789987654321123456789987654321"),
49 L("-12345678987654321123456789987654321123456789987654321"),
50 L("-12,345,678987,654,321123,456,789987,654,321123,456,789987,654,321"),
51 L("-12,345,678987,654,321123,456,789987,654,321123,456,789987,654,321")
54 const CHAR *fmt_long[] =
56 L("%9ld%9ld%9ld%9ld%9ld%9ld"),
57 L("%I9ld%I9ld%I9ld%I9ld%I9ld%I9ld"),
58 L("%'11ld%'11ld%'11ld%'11ld%'11ld%'11ld"),
59 L("%I'11ld%I'11ld%I'11ld%I'11ld%I'11ld%I'11ld")
62 const long int val_long[] =
64 -12345678, 987654321, 123456789, 987654321, 123456789, 987654321
67 struct test
69 const CHAR *str;
70 const CHAR *fmt;
71 int retval;
72 } int_tests[] =
74 { L("foo\n"), L("foo\nbar"), -1 },
75 { L("foo\n"), L("foo bar"), -1 },
76 { L("foo\n"), L("foo %d"), -1 },
77 { L("foo\n"), L("foo\n%d"), -1 },
78 { L("foon"), L("foonbar"), -1 },
79 { L("foon"), L("foon%d"), -1 },
80 { L("foo "), L("foo bar"), -1 },
81 { L("foo "), L("foo %d"), -1 },
82 { L("foo\t"), L("foo\tbar"), -1 },
83 { L("foo\t"), L("foo bar"), -1 },
84 { L("foo\t"), L("foo %d"), -1 },
85 { L("foo\t"), L("foo\t%d"), -1 },
86 { L("foo"), L("foo"), 0 },
87 { L("foon"), L("foo bar"), 0 },
88 { L("foon"), L("foo %d"), 0 },
89 { L("foo "), L("fooxbar"), 0 },
90 { L("foo "), L("foox%d"), 0 },
91 { L("foo bar"), L("foon"), 0 },
92 { L("foo bar"), L("foo bar"), 0 },
93 { L("foo bar"), L("foo %d"), 0 },
94 { L("foo bar"), L("foon%d"), 0 },
95 { L("foo (nil)"), L("foo %p"), 1},
96 { L("foo (nil)"), L("foo %4p"), 0},
97 { L("foo "), L("foo %n"), 0 },
98 { L("foo%bar1"), L("foo%%bar%d"), 1 },
99 /* Some OSes skip whitespace here while others don't. */
100 { L("foo \t %bar1"), L("foo%%bar%d"), 1 }
103 struct test double_tests[] =
105 { L("-1"), L("%1g"), 0 },
106 { L("-.1"), L("%2g"), 0 },
107 { L("-inf"), L("%3g"), 0 },
108 { L("+0"), L("%1g"), },
109 { L("-0x1p0"), L("%2g"), 1 },
110 { L("-..1"), L("%g"), 0 },
111 { L("-inf"), L("%g"), 1 }
114 struct test2
116 const CHAR *str;
117 const CHAR *fmt;
118 int retval;
119 char residual;
120 } double_tests2[] =
122 { L("0e+0"), L("%g%c"), 1, 0 },
123 { L("0xe+0"), L("%g%c"), 2, '+' },
124 { L("0x.e+0"), L("%g%c"), 2, '+' },
127 static int
128 do_test (void)
130 double d[6];
131 long l[6];
132 int i, j;
133 int tst_locale;
134 int result = 0;
136 tst_locale = 1;
137 if (tst_locale)
138 if (setlocale (LC_ALL, "en_US.ISO-8859-1") == NULL)
140 puts ("Failed to set en_US locale, skipping locale related tests");
141 tst_locale = 0;
144 for (i = 0; i < 4; ++i)
146 if (SSCANF (str_double[i], L("%11lf%11lf%11lf%11lf%11lf%11lf"),
147 &d[0], &d[1], &d[2], &d[3], &d[4], &d[5]) != 6)
149 printf ("Double sscanf test %d wrong number of "
150 "assigned inputs\n", i);
151 result = 1;
153 else
154 for (j = 0; j < 6; ++j)
155 if (d[j] != val_double[6 * i + j])
157 printf ("Double sscanf test %d failed (%g instead of %g)\n",
158 i, d[j], val_double[6 * i + j]);
159 result = 1;
160 break;
164 for (i = 0; i < 4; ++i)
166 if (SSCANF (str_long[i], fmt_long[i],
167 &l[0], &l[1], &l[2], &l[3], &l[4], &l[5]) != 6)
169 printf ("Integer sscanf test %d wrong number of "
170 "assigned inputs\n", i);
171 result = 1;
173 else
174 for (j = 0; j < 6; ++j)
175 if (l[j] != val_long[j])
177 printf ("Integer sscanf test %d failed (%ld instead %ld)\n",
178 i, l[j], val_long[j]);
179 result = 1;
180 break;
183 if (! tst_locale)
184 break;
187 for (i = 0; i < array_length (int_tests); ++i)
189 long dummy;
190 int ret;
192 if ((ret = SSCANF (int_tests[i].str, int_tests[i].fmt,
193 &dummy)) != int_tests[i].retval)
195 printf ("int_tests[%d] returned %d != %d\n",
196 i, ret, int_tests[i].retval);
197 result = 1;
201 for (i = 0; i < array_length (double_tests); ++i)
203 double dummy;
204 int ret;
206 if ((ret = SSCANF (double_tests[i].str, double_tests[i].fmt,
207 &dummy)) != double_tests[i].retval)
209 printf ("double_tests[%d] returned %d != %d\n",
210 i, ret, double_tests[i].retval);
211 result = 1;
215 for (i = 0; i < array_length (double_tests2); ++i)
217 double dummy;
218 int ret;
219 char c = 0;
221 if ((ret = SSCANF (double_tests2[i].str, double_tests2[i].fmt,
222 &dummy, &c)) != double_tests2[i].retval)
224 printf ("double_tests2[%d] returned %d != %d\n",
225 i, ret, double_tests2[i].retval);
226 result = 1;
228 else if (ret == 2 && c != double_tests2[i].residual)
230 printf ("double_tests2[%d] stopped at '%c' != '%c'\n",
231 i, c, double_tests2[i].residual);
232 result = 1;
236 /* BZ #16618
237 The test will segfault during SSCANF if the buffer overflow
238 is not fixed. The size of `s` is such that it forces the use
239 of malloc internally and this triggers the incorrect computation.
240 Thus the value for SIZE is arbitrarily high enough that malloc
241 is used. */
243 #define SIZE 131072
244 CHAR *s = malloc ((SIZE + 1) * sizeof (*s));
245 if (s == NULL)
246 abort ();
247 for (size_t i = 0; i < SIZE; i++)
248 s[i] = L('0');
249 s[SIZE] = L('\0');
250 int i = 42;
251 /* Scan multi-digit zero into `i`. */
252 if (SSCANF (s, L("%d"), &i) != 1)
254 printf ("FAIL: bug16618: SSCANF did not read one input item.\n");
255 result = 1;
257 if (i != 0)
259 printf ("FAIL: bug16618: Value of `i` was not zero as expected.\n");
260 result = 1;
262 free (s);
263 if (result != 1)
264 printf ("PASS: bug16618: Did not crash.\n");
265 #undef SIZE
269 return result;
272 #define TEST_FUNCTION do_test ()
273 #include "../test-skeleton.c"