1 | //===-- Unittests for sscanf ----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/stdio/vsscanf.h" |
10 | |
11 | #include "test/UnitTest/Test.h" |
12 | |
13 | int call_vsscanf(const char *__restrict buffer, const char *__restrict format, |
14 | ...) { |
15 | va_list vlist; |
16 | va_start(vlist, format); |
17 | int ret = LIBC_NAMESPACE::vsscanf(buffer, format, vlist); |
18 | va_end(vlist); |
19 | return ret; |
20 | } |
21 | |
22 | TEST(LlvmLibcVSScanfTest, SimpleStringConv) { |
23 | int ret_val; |
24 | char buffer[10]; |
25 | char buffer2[10]; |
26 | ret_val = call_vsscanf(buffer: "abc123" , format: "abc %s" , buffer); |
27 | ASSERT_EQ(ret_val, 1); |
28 | ASSERT_STREQ(buffer, "123" ); |
29 | |
30 | ret_val = call_vsscanf(buffer: "abc123" , format: "%3s %3s" , buffer, buffer2); |
31 | ASSERT_EQ(ret_val, 2); |
32 | ASSERT_STREQ(buffer, "abc" ); |
33 | ASSERT_STREQ(buffer2, "123" ); |
34 | |
35 | ret_val = call_vsscanf(buffer: "abc 123" , format: "%3s%3s" , buffer, buffer2); |
36 | ASSERT_EQ(ret_val, 2); |
37 | ASSERT_STREQ(buffer, "abc" ); |
38 | ASSERT_STREQ(buffer2, "123" ); |
39 | } |
40 | |
41 | TEST(LlvmLibcVSScanfTest, IntConvSimple) { |
42 | int ret_val; |
43 | int result = 0; |
44 | ret_val = call_vsscanf(buffer: "123" , format: "%d" , &result); |
45 | EXPECT_EQ(ret_val, 1); |
46 | EXPECT_EQ(result, 123); |
47 | |
48 | ret_val = call_vsscanf(buffer: "456" , format: "%i" , &result); |
49 | EXPECT_EQ(ret_val, 1); |
50 | EXPECT_EQ(result, 456); |
51 | |
52 | ret_val = call_vsscanf(buffer: "789" , format: "%x" , &result); |
53 | EXPECT_EQ(ret_val, 1); |
54 | EXPECT_EQ(result, 0x789); |
55 | |
56 | ret_val = call_vsscanf(buffer: "012" , format: "%o" , &result); |
57 | EXPECT_EQ(ret_val, 1); |
58 | EXPECT_EQ(result, 012); |
59 | |
60 | ret_val = call_vsscanf(buffer: "345" , format: "%u" , &result); |
61 | EXPECT_EQ(ret_val, 1); |
62 | EXPECT_EQ(result, 345); |
63 | |
64 | // 288 characters |
65 | ret_val = call_vsscanf(buffer: "10000000000000000000000000000000" |
66 | "00000000000000000000000000000000" |
67 | "00000000000000000000000000000000" |
68 | "00000000000000000000000000000000" |
69 | "00000000000000000000000000000000" |
70 | "00000000000000000000000000000000" |
71 | "00000000000000000000000000000000" |
72 | "00000000000000000000000000000000" |
73 | "00000000000000000000000000000000" , |
74 | format: "%d" , &result); |
75 | EXPECT_EQ(ret_val, 1); |
76 | EXPECT_EQ(result, int(LIBC_NAMESPACE::cpp::numeric_limits<intmax_t>::max())); |
77 | |
78 | ret_val = call_vsscanf(buffer: "Not an integer" , format: "%d" , &result); |
79 | EXPECT_EQ(ret_val, 0); |
80 | } |
81 | |
82 | TEST(LlvmLibcVSScanfTest, IntConvLengthModifier) { |
83 | int ret_val; |
84 | uintmax_t max_result = 0; |
85 | int int_result = 0; |
86 | char char_result = 0; |
87 | |
88 | ret_val = call_vsscanf("123" , "%ju" , &max_result); |
89 | EXPECT_EQ(ret_val, 1); |
90 | EXPECT_EQ(max_result, uintmax_t(123)); |
91 | |
92 | // Check overflow handling |
93 | ret_val = |
94 | call_vsscanf("999999999999999999999999999999999999" , "%ju" , &max_result); |
95 | EXPECT_EQ(ret_val, 1); |
96 | EXPECT_EQ(max_result, LIBC_NAMESPACE::cpp::numeric_limits<uintmax_t>::max()); |
97 | |
98 | // Because this is unsigned, any out of range value should return the maximum, |
99 | // even with a negative sign. |
100 | ret_val = |
101 | call_vsscanf("-999999999999999999999999999999999999" , "%ju" , &max_result); |
102 | EXPECT_EQ(ret_val, 1); |
103 | EXPECT_EQ(max_result, LIBC_NAMESPACE::cpp::numeric_limits<uintmax_t>::max()); |
104 | |
105 | ret_val = call_vsscanf("-18446744073709551616" , "%ju" , &max_result); |
106 | EXPECT_EQ(ret_val, 1); |
107 | EXPECT_EQ(max_result, LIBC_NAMESPACE::cpp::numeric_limits<uintmax_t>::max()); |
108 | |
109 | // But any number below the maximum should have the - sign applied. |
110 | ret_val = call_vsscanf("-1" , "%ju" , &max_result); |
111 | EXPECT_EQ(ret_val, 1); |
112 | EXPECT_EQ(max_result, uintmax_t(-1)); |
113 | |
114 | ret_val = call_vsscanf(buffer: "-1" , format: "%u" , &int_result); |
115 | EXPECT_EQ(ret_val, 1); |
116 | EXPECT_EQ(int_result, -1); |
117 | |
118 | max_result = 0xff00ff00ff00ff00; |
119 | char_result = 0x6f; |
120 | |
121 | // Overflows for sizes larger than the maximum are handled by casting. |
122 | ret_val = call_vsscanf(buffer: "8589967360" , format: "%d" , &int_result); |
123 | EXPECT_EQ(ret_val, 1); |
124 | EXPECT_EQ(int_result, int(8589967360)); // 2^33 + 2^15 |
125 | |
126 | // Check that the adjacent values weren't touched by the overflow. |
127 | ASSERT_EQ(max_result, uintmax_t(0xff00ff00ff00ff00)); |
128 | ASSERT_EQ(char_result, char(0x6f)); |
129 | |
130 | ret_val = call_vsscanf(buffer: "-8589967360" , format: "%d" , &int_result); |
131 | EXPECT_EQ(ret_val, 1); |
132 | EXPECT_EQ(int_result, int(-8589967360)); |
133 | ASSERT_EQ(max_result, uintmax_t(0xff00ff00ff00ff00)); |
134 | ASSERT_EQ(char_result, char(0x6f)); |
135 | |
136 | ret_val = call_vsscanf(buffer: "25" , format: "%hhd" , &char_result); |
137 | EXPECT_EQ(ret_val, 1); |
138 | EXPECT_EQ(char_result, char(25)); |
139 | } |
140 | |
141 | TEST(LlvmLibcVSScanfTest, IntConvBaseSelection) { |
142 | int ret_val; |
143 | int result = 0; |
144 | ret_val = call_vsscanf(buffer: "0xabc123" , format: "%i" , &result); |
145 | EXPECT_EQ(ret_val, 1); |
146 | EXPECT_EQ(result, 0xabc123); |
147 | |
148 | ret_val = call_vsscanf(buffer: "0456" , format: "%i" , &result); |
149 | EXPECT_EQ(ret_val, 1); |
150 | EXPECT_EQ(result, 0456); |
151 | |
152 | ret_val = call_vsscanf(buffer: "0999" , format: "%i" , &result); |
153 | EXPECT_EQ(ret_val, 1); |
154 | EXPECT_EQ(result, 0); |
155 | |
156 | ret_val = call_vsscanf(buffer: "123abc456" , format: "%i" , &result); |
157 | EXPECT_EQ(ret_val, 1); |
158 | EXPECT_EQ(result, 123); |
159 | } |
160 | |