1 /*-
2 * Copyright (c) 2023 Dag-Erling Smørgrav
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <limits.h>
8 #include <locale.h>
9 #include <stdint.h>
10 #include <stdio.h>
11
12 #include <atf-c.h>
13
14 static const struct sscanf_test_case {
15 char input[8];
16 struct {
17 int ret, val, len;
18 } b, o, d, x, i;
19 } sscanf_test_cases[] = {
20 // input binary octal decimal hexadecimal automatic
21 // all digits
22 { "0", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
23 { "1", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
24 { "2", { 0, 0, 0 }, { 1, 2, 1 }, { 1, 2, 1 }, { 1, 2, 1 }, { 1, 2, 1 }, },
25 { "3", { 0, 0, 0 }, { 1, 3, 1 }, { 1, 3, 1 }, { 1, 3, 1 }, { 1, 3, 1 }, },
26 { "4", { 0, 0, 0 }, { 1, 4, 1 }, { 1, 4, 1 }, { 1, 4, 1 }, { 1, 4, 1 }, },
27 { "5", { 0, 0, 0 }, { 1, 5, 1 }, { 1, 5, 1 }, { 1, 5, 1 }, { 1, 5, 1 }, },
28 { "6", { 0, 0, 0 }, { 1, 6, 1 }, { 1, 6, 1 }, { 1, 6, 1 }, { 1, 6, 1 }, },
29 { "7", { 0, 0, 0 }, { 1, 7, 1 }, { 1, 7, 1 }, { 1, 7, 1 }, { 1, 7, 1 }, },
30 { "8", { 0, 0, 0 }, { 0, 0, 0 }, { 1, 8, 1 }, { 1, 8, 1 }, { 1, 8, 1 }, },
31 { "9", { 0, 0, 0 }, { 0, 0, 0 }, { 1, 9, 1 }, { 1, 9, 1 }, { 1, 9, 1 }, },
32 { "A", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 10, 1 }, { 0, 0, 0 }, },
33 { "B", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 11, 1 }, { 0, 0, 0 }, },
34 { "C", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 12, 1 }, { 0, 0, 0 }, },
35 { "D", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 13, 1 }, { 0, 0, 0 }, },
36 { "E", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 14, 1 }, { 0, 0, 0 }, },
37 { "F", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 15, 1 }, { 0, 0, 0 }, },
38 { "X", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, },
39 { "a", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 10, 1 }, { 0, 0, 0 }, },
40 { "b", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 11, 1 }, { 0, 0, 0 }, },
41 { "c", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 12, 1 }, { 0, 0, 0 }, },
42 { "d", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 13, 1 }, { 0, 0, 0 }, },
43 { "e", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 14, 1 }, { 0, 0, 0 }, },
44 { "f", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1, 15, 1 }, { 0, 0, 0 }, },
45 { "x", { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, },
46 // all digits with leading zero
47 { "00", { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, { 1, 0, 2 }, },
48 { "01", { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 }, },
49 { "02", { 1, 0, 1 }, { 1, 2, 2 }, { 1, 2, 2 }, { 1, 2, 2 }, { 1, 2, 2 }, },
50 { "03", { 1, 0, 1 }, { 1, 3, 2 }, { 1, 3, 2 }, { 1, 3, 2 }, { 1, 3, 2 }, },
51 { "04", { 1, 0, 1 }, { 1, 4, 2 }, { 1, 4, 2 }, { 1, 4, 2 }, { 1, 4, 2 }, },
52 { "05", { 1, 0, 1 }, { 1, 5, 2 }, { 1, 5, 2 }, { 1, 5, 2 }, { 1, 5, 2 }, },
53 { "06", { 1, 0, 1 }, { 1, 6, 2 }, { 1, 6, 2 }, { 1, 6, 2 }, { 1, 6, 2 }, },
54 { "07", { 1, 0, 1 }, { 1, 7, 2 }, { 1, 7, 2 }, { 1, 7, 2 }, { 1, 7, 2 }, },
55 { "08", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 8, 2 }, { 1, 8, 2 }, { 1, 0, 1 }, },
56 { "09", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 9, 2 }, { 1, 9, 2 }, { 1, 0, 1 }, },
57 { "0A", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 2 }, { 1, 0, 1 }, },
58 { "0B", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
59 { "0C", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 2 }, { 1, 0, 1 }, },
60 { "0D", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 2 }, { 1, 0, 1 }, },
61 { "0E", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
62 { "0F", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
63 { "0X", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
64 { "0a", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 2 }, { 1, 0, 1 }, },
65 { "0b", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
66 { "0c", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 2 }, { 1, 0, 1 }, },
67 { "0d", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 2 }, { 1, 0, 1 }, },
68 { "0e", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 2 }, { 1, 0, 1 }, },
69 { "0f", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 2 }, { 1, 0, 1 }, },
70 { "0x", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
71 // all digits with leading one
72 { "10", { 1, 2, 2 }, { 1, 8, 2 }, { 1, 10, 2 }, { 1, 16, 2 }, { 1, 10, 2 }, },
73 { "11", { 1, 3, 2 }, { 1, 9, 2 }, { 1, 11, 2 }, { 1, 17, 2 }, { 1, 11, 2 }, },
74 { "12", { 1, 1, 1 }, { 1, 10, 2 }, { 1, 12, 2 }, { 1, 18, 2 }, { 1, 12, 2 }, },
75 { "13", { 1, 1, 1 }, { 1, 11, 2 }, { 1, 13, 2 }, { 1, 19, 2 }, { 1, 13, 2 }, },
76 { "14", { 1, 1, 1 }, { 1, 12, 2 }, { 1, 14, 2 }, { 1, 20, 2 }, { 1, 14, 2 }, },
77 { "15", { 1, 1, 1 }, { 1, 13, 2 }, { 1, 15, 2 }, { 1, 21, 2 }, { 1, 15, 2 }, },
78 { "16", { 1, 1, 1 }, { 1, 14, 2 }, { 1, 16, 2 }, { 1, 22, 2 }, { 1, 16, 2 }, },
79 { "17", { 1, 1, 1 }, { 1, 15, 2 }, { 1, 17, 2 }, { 1, 23, 2 }, { 1, 17, 2 }, },
80 { "18", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 18, 2 }, { 1, 24, 2 }, { 1, 18, 2 }, },
81 { "19", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 19, 2 }, { 1, 25, 2 }, { 1, 19, 2 }, },
82 { "1A", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 26, 2 }, { 1, 1, 1 }, },
83 { "1B", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 27, 2 }, { 1, 1, 1 }, },
84 { "1C", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 28, 2 }, { 1, 1, 1 }, },
85 { "1D", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 29, 2 }, { 1, 1, 1 }, },
86 { "1E", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 30, 2 }, { 1, 1, 1 }, },
87 { "1F", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 31, 2 }, { 1, 1, 1 }, },
88 { "1X", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
89 { "1a", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 26, 2 }, { 1, 1, 1 }, },
90 { "1b", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 27, 2 }, { 1, 1, 1 }, },
91 { "1c", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 28, 2 }, { 1, 1, 1 }, },
92 { "1d", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 29, 2 }, { 1, 1, 1 }, },
93 { "1e", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 30, 2 }, { 1, 1, 1 }, },
94 { "1f", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 31, 2 }, { 1, 1, 1 }, },
95 { "1x", { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, },
96 // all digits with leading binary prefix
97 { "0b0", { 1, 0, 3 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 176, 3 }, { 1, 0, 3 }, },
98 { "0b1", { 1, 1, 3 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 177, 3 }, { 1, 1, 3 }, },
99 { "0b2", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 178, 3 }, { 1, 0, 1 }, },
100 { "0b3", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 179, 3 }, { 1, 0, 1 }, },
101 { "0b4", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 180, 3 }, { 1, 0, 1 }, },
102 { "0b5", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 181, 3 }, { 1, 0, 1 }, },
103 { "0b6", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 182, 3 }, { 1, 0, 1 }, },
104 { "0b7", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 183, 3 }, { 1, 0, 1 }, },
105 { "0b8", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 184, 3 }, { 1, 0, 1 }, },
106 { "0b9", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 185, 3 }, { 1, 0, 1 }, },
107 { "0bA", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 186, 3 }, { 1, 0, 1 }, },
108 { "0bB", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 187, 3 }, { 1, 0, 1 }, },
109 { "0bC", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 188, 3 }, { 1, 0, 1 }, },
110 { "0bD", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 189, 3 }, { 1, 0, 1 }, },
111 { "0bE", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 190, 3 }, { 1, 0, 1 }, },
112 { "0bF", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 191, 3 }, { 1, 0, 1 }, },
113 { "0bX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
114 { "0ba", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 186, 3 }, { 1, 0, 1 }, },
115 { "0bb", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 187, 3 }, { 1, 0, 1 }, },
116 { "0bc", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 188, 3 }, { 1, 0, 1 }, },
117 { "0bd", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 189, 3 }, { 1, 0, 1 }, },
118 { "0be", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 190, 3 }, { 1, 0, 1 }, },
119 { "0bf", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 191, 3 }, { 1, 0, 1 }, },
120 { "0bx", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 2 }, { 1, 0, 1 }, },
121 // all digits with leading hexadecimal prefix
122 { "0x0", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 3 }, { 1, 0, 3 }, },
123 { "0x1", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 1, 3 }, { 1, 1, 3 }, },
124 { "0x2", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 2, 3 }, { 1, 2, 3 }, },
125 { "0x3", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 3, 3 }, { 1, 3, 3 }, },
126 { "0x4", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 4, 3 }, { 1, 4, 3 }, },
127 { "0x5", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 5, 3 }, { 1, 5, 3 }, },
128 { "0x6", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 6, 3 }, { 1, 6, 3 }, },
129 { "0x7", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 7, 3 }, { 1, 7, 3 }, },
130 { "0x8", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 8, 3 }, { 1, 8, 3 }, },
131 { "0x9", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 9, 3 }, { 1, 9, 3 }, },
132 { "0xA", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 3 }, { 1, 10, 3 }, },
133 { "0xB", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 3 }, { 1, 11, 3 }, },
134 { "0xC", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 3 }, { 1, 12, 3 }, },
135 { "0xD", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 3 }, { 1, 13, 3 }, },
136 { "0xE", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 3 }, { 1, 14, 3 }, },
137 { "0xF", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 3 }, { 1, 15, 3 }, },
138 { "0xX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
139 { "0xa", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 10, 3 }, { 1, 10, 3 }, },
140 { "0xb", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 11, 3 }, { 1, 11, 3 }, },
141 { "0xc", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 12, 3 }, { 1, 12, 3 }, },
142 { "0xd", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 13, 3 }, { 1, 13, 3 }, },
143 { "0xe", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 14, 3 }, { 1, 14, 3 }, },
144 { "0xf", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 15, 3 }, { 1, 15, 3 }, },
145 { "0xX", { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, },
146 // terminator
147 { "" }
148 };
149
150 #define SSCANF_TEST(string, format, expret, expval, explen) \
151 do { \
152 int ret = 0, val = 0, len = 0; \
153 ret = sscanf(string, format "%n", &val, &len); \
154 ATF_CHECK_EQ(expret, ret); \
155 if (expret && ret) { \
156 ATF_CHECK_EQ(expval, val); \
157 ATF_CHECK_EQ(explen, len); \
158 } \
159 } while (0)
160
161 ATF_TC_WITHOUT_HEAD(sscanf_b);
ATF_TC_BODY(sscanf_b,tc)162 ATF_TC_BODY(sscanf_b, tc)
163 {
164 const struct sscanf_test_case *stc;
165 char input[16];
166
167 for (stc = sscanf_test_cases; *stc->input; stc++) {
168 strcpy(input + 1, stc->input);
169 SSCANF_TEST(input + 1, "%b", stc->b.ret, stc->b.val, stc->b.len);
170 input[0] = '+';
171 SSCANF_TEST(input, "%b", stc->b.ret, stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
172 input[0] = '-';
173 SSCANF_TEST(input, "%b", stc->b.ret, -stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
174 }
175 }
176
177 ATF_TC_WITHOUT_HEAD(sscanf_o);
ATF_TC_BODY(sscanf_o,tc)178 ATF_TC_BODY(sscanf_o, tc)
179 {
180 const struct sscanf_test_case *stc;
181 char input[16];
182
183 for (stc = sscanf_test_cases; *stc->input; stc++) {
184 strcpy(input + 1, stc->input);
185 SSCANF_TEST(input + 1, "%o", stc->o.ret, stc->o.val, stc->o.len);
186 input[0] = '+';
187 SSCANF_TEST(input, "%o", stc->o.ret, stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
188 input[0] = '-';
189 SSCANF_TEST(input, "%o", stc->o.ret, -stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
190 }
191 }
192
193 ATF_TC_WITHOUT_HEAD(sscanf_d);
ATF_TC_BODY(sscanf_d,tc)194 ATF_TC_BODY(sscanf_d, tc)
195 {
196 const struct sscanf_test_case *stc;
197 char input[16];
198
199 for (stc = sscanf_test_cases; *stc->input; stc++) {
200 strcpy(input + 1, stc->input);
201 SSCANF_TEST(input + 1, "%d", stc->d.ret, stc->d.val, stc->d.len);
202 input[0] = '+';
203 SSCANF_TEST(input, "%d", stc->d.ret, stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
204 input[0] = '-';
205 SSCANF_TEST(input, "%d", stc->d.ret, -stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
206 }
207 }
208
209 ATF_TC_WITHOUT_HEAD(sscanf_x);
ATF_TC_BODY(sscanf_x,tc)210 ATF_TC_BODY(sscanf_x, tc)
211 {
212 const struct sscanf_test_case *stc;
213 char input[16];
214
215 for (stc = sscanf_test_cases; *stc->input; stc++) {
216 strcpy(input + 1, stc->input);
217 SSCANF_TEST(input + 1, "%x", stc->x.ret, stc->x.val, stc->x.len);
218 input[0] = '+';
219 SSCANF_TEST(input, "%x", stc->x.ret, stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
220 input[0] = '-';
221 SSCANF_TEST(input, "%x", stc->x.ret, -stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
222 }
223 }
224
225 ATF_TC_WITHOUT_HEAD(sscanf_i);
ATF_TC_BODY(sscanf_i,tc)226 ATF_TC_BODY(sscanf_i, tc)
227 {
228 const struct sscanf_test_case *stc;
229 char input[16];
230
231 for (stc = sscanf_test_cases; *stc->input; stc++) {
232 strcpy(input + 1, stc->input);
233 SSCANF_TEST(input + 1, "%i", stc->i.ret, stc->i.val, stc->i.len);
234 input[0] = '+';
235 SSCANF_TEST(input, "%i", stc->i.ret, stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
236 input[0] = '-';
237 SSCANF_TEST(input, "%i", stc->i.ret, -stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
238 }
239 }
240
241 ATF_TC_WITHOUT_HEAD(sscanf_wN);
ATF_TC_BODY(sscanf_wN,tc)242 ATF_TC_BODY(sscanf_wN, tc)
243 {
244 const char x00[] = "0x00";
245 const char x7f[] = "0x7fffffffffffffff";
246 const char xff[] = "0xffffffffffffffff";
247
248 #define SSCANF_WN_TEST(N, imin, umax) \
249 do { \
250 int##N##_t i; \
251 uint##N##_t u; \
252 ATF_CHECK_EQ(1, sscanf(x00, "%w" #N "i", &i)); \
253 ATF_CHECK_EQ(0, i); \
254 ATF_CHECK_EQ(1, sscanf(x7f, "%w" #N "i", &i)); \
255 ATF_CHECK_EQ(imin, i); \
256 ATF_CHECK_EQ(1, sscanf(x00, "%w" #N "x", &u)); \
257 ATF_CHECK_EQ(0, u); \
258 ATF_CHECK_EQ(1, sscanf(xff, "%w" #N "x", &u)); \
259 ATF_CHECK_EQ(umax, u); \
260 } while (0)
261 SSCANF_WN_TEST(8, -1, UCHAR_MAX);
262 SSCANF_WN_TEST(16, -1, USHRT_MAX);
263 SSCANF_WN_TEST(32, -1, UINT_MAX);
264 SSCANF_WN_TEST(64, LLONG_MAX, ULLONG_MAX);
265 #undef SSCANF_WN_TEST
266
267 ATF_CHECK_EQ(0, sscanf(x00, "%wi", (int *)NULL));
268 ATF_CHECK_EQ(0, sscanf(x00, "%w1i", (int *)NULL));
269 ATF_CHECK_EQ(0, sscanf(x00, "%w128i", (int *)NULL));
270 }
271
272 ATF_TC_WITHOUT_HEAD(sscanf_wfN);
ATF_TC_BODY(sscanf_wfN,tc)273 ATF_TC_BODY(sscanf_wfN, tc)
274 {
275 const char x00[] = "0x00";
276 const char x7f[] = "0x7fffffffffffffff";
277 const char xff[] = "0xffffffffffffffff";
278
279 #define SSCANF_WFN_TEST(N, imin, umax) \
280 do { \
281 int_fast##N##_t i; \
282 uint_fast##N##_t u; \
283 ATF_CHECK_EQ(1, sscanf(x00, "%wf" #N "i", &i)); \
284 ATF_CHECK_EQ(0, i); \
285 ATF_CHECK_EQ(1, sscanf(x7f, "%wf" #N "i", &i)); \
286 ATF_CHECK_EQ(imin, i); \
287 ATF_CHECK_EQ(1, sscanf(x00, "%wf" #N "x", &u)); \
288 ATF_CHECK_EQ(0, u); \
289 ATF_CHECK_EQ(1, sscanf(xff, "%wf" #N "x", &u)); \
290 ATF_CHECK_EQ(umax, u); \
291 } while (0)
292 SSCANF_WFN_TEST(8, -1, UINT_MAX);
293 SSCANF_WFN_TEST(16, -1, UINT_MAX);
294 SSCANF_WFN_TEST(32, -1, UINT_MAX);
295 SSCANF_WFN_TEST(64, LLONG_MAX, ULLONG_MAX);
296 #undef SSCANF_WFN_TEST
297
298 ATF_CHECK_EQ(0, sscanf(x00, "%wfi", (int *)NULL));
299 ATF_CHECK_EQ(0, sscanf(x00, "%wf1i", (int *)NULL));
300 ATF_CHECK_EQ(0, sscanf(x00, "%wf128i", (int *)NULL));
301 }
302
303 /*
304 * Test termination cases: non-numeric character, fixed width, EOF
305 */
306 ATF_TC_WITHOUT_HEAD(sscanf_termination);
ATF_TC_BODY(sscanf_termination,tc)307 ATF_TC_BODY(sscanf_termination, tc)
308 {
309 int a = 0, b = 0, c = 0;
310 char d = 0;
311
312 ATF_CHECK_EQ(4, sscanf("3.1415", "%d%c%2d%d", &a, &d, &b, &c));
313 ATF_CHECK_EQ(3, a);
314 ATF_CHECK_EQ(14, b);
315 ATF_CHECK_EQ(15, c);
316 ATF_CHECK_EQ('.', d);
317 }
318
ATF_TP_ADD_TCS(tp)319 ATF_TP_ADD_TCS(tp)
320 {
321 setlocale(LC_NUMERIC, "en_US.UTF-8");
322 ATF_TP_ADD_TC(tp, sscanf_b);
323 ATF_TP_ADD_TC(tp, sscanf_o);
324 ATF_TP_ADD_TC(tp, sscanf_d);
325 ATF_TP_ADD_TC(tp, sscanf_x);
326 ATF_TP_ADD_TC(tp, sscanf_i);
327 ATF_TP_ADD_TC(tp, sscanf_wN);
328 ATF_TP_ADD_TC(tp, sscanf_wfN);
329 ATF_TP_ADD_TC(tp, sscanf_termination);
330 return (atf_no_error());
331 }
332