1/* Copyright (C) 2000-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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/>. */
17
18#include <array_length.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <locale.h>
22
23#ifndef CHAR
24# define CHAR char
25# define L(str) str
26# define SSCANF sscanf
27#endif
28
29const CHAR *str_double[] =
30{
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")
35};
36
37const double val_double[] =
38{
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
44};
45
46const CHAR *str_long[] =
47{
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")
52};
53
54const CHAR *fmt_long[] =
55{
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")
60};
61
62const long int val_long[] =
63{
64 -12345678, 987654321, 123456789, 987654321, 123456789, 987654321
65};
66
67struct test
68{
69 const CHAR *str;
70 const CHAR *fmt;
71 int retval;
72} int_tests[] =
73{
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 }
101};
102
103struct test double_tests[] =
104{
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 }
112};
113
114struct test2
115{
116 const CHAR *str;
117 const CHAR *fmt;
118 int retval;
119 char residual;
120} double_tests2[] =
121{
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, '+' },
125};
126
127static int
128do_test (void)
129{
130 double d[6];
131 long l[6];
132 int i, j;
133 int tst_locale;
134 int result = 0;
135
136 tst_locale = 1;
137 if (tst_locale)
138 if (setlocale (LC_ALL, "en_US.ISO-8859-1") == NULL)
139 {
140 puts (s: "Failed to set en_US locale, skipping locale related tests");
141 tst_locale = 0;
142 }
143
144 for (i = 0; i < 4; ++i)
145 {
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)
148 {
149 printf (format: "Double sscanf test %d wrong number of "
150 "assigned inputs\n", i);
151 result = 1;
152 }
153 else
154 for (j = 0; j < 6; ++j)
155 if (d[j] != val_double[6 * i + j])
156 {
157 printf (format: "Double sscanf test %d failed (%g instead of %g)\n",
158 i, d[j], val_double[6 * i + j]);
159 result = 1;
160 break;
161 }
162 }
163
164 for (i = 0; i < 4; ++i)
165 {
166 if (SSCANF (str_long[i], fmt_long[i],
167 &l[0], &l[1], &l[2], &l[3], &l[4], &l[5]) != 6)
168 {
169 printf (format: "Integer sscanf test %d wrong number of "
170 "assigned inputs\n", i);
171 result = 1;
172 }
173 else
174 for (j = 0; j < 6; ++j)
175 if (l[j] != val_long[j])
176 {
177 printf (format: "Integer sscanf test %d failed (%ld instead %ld)\n",
178 i, l[j], val_long[j]);
179 result = 1;
180 break;
181 }
182
183 if (! tst_locale)
184 break;
185 }
186
187 for (i = 0; i < array_length (int_tests); ++i)
188 {
189 long dummy;
190 int ret;
191
192 if ((ret = SSCANF (int_tests[i].str, int_tests[i].fmt,
193 &dummy)) != int_tests[i].retval)
194 {
195 printf (format: "int_tests[%d] returned %d != %d\n",
196 i, ret, int_tests[i].retval);
197 result = 1;
198 }
199 }
200
201 for (i = 0; i < array_length (double_tests); ++i)
202 {
203 double dummy;
204 int ret;
205
206 if ((ret = SSCANF (double_tests[i].str, double_tests[i].fmt,
207 &dummy)) != double_tests[i].retval)
208 {
209 printf (format: "double_tests[%d] returned %d != %d\n",
210 i, ret, double_tests[i].retval);
211 result = 1;
212 }
213 }
214
215 for (i = 0; i < array_length (double_tests2); ++i)
216 {
217 double dummy;
218 int ret;
219 char c = 0;
220
221 if ((ret = SSCANF (double_tests2[i].str, double_tests2[i].fmt,
222 &dummy, &c)) != double_tests2[i].retval)
223 {
224 printf (format: "double_tests2[%d] returned %d != %d\n",
225 i, ret, double_tests2[i].retval);
226 result = 1;
227 }
228 else if (ret == 2 && c != double_tests2[i].residual)
229 {
230 printf (format: "double_tests2[%d] stopped at '%c' != '%c'\n",
231 i, c, double_tests2[i].residual);
232 result = 1;
233 }
234 }
235
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 arbitrariy high enough that malloc
241 is used. */
242 {
243#define SIZE 131072
244 CHAR *s = malloc (size: (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)
253 {
254 printf (format: "FAIL: bug16618: SSCANF did not read one input item.\n");
255 result = 1;
256 }
257 if (i != 0)
258 {
259 printf (format: "FAIL: bug16618: Value of `i` was not zero as expected.\n");
260 result = 1;
261 }
262 free (ptr: s);
263 if (result != 1)
264 printf (format: "PASS: bug16618: Did not crash.\n");
265#undef SIZE
266 }
267
268
269 return result;
270}
271
272#define TEST_FUNCTION do_test ()
273#include "../test-skeleton.c"
274

source code of glibc/stdio-common/tst-sscanf.c