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
call_vsscanf(const char * __restrict buffer,const char * __restrict format,...)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
TEST(LlvmLibcVSScanfTest,SimpleStringConv)22 TEST(LlvmLibcVSScanfTest, SimpleStringConv) {
23 int ret_val;
24 char buffer[10];
25 char buffer2[10];
26 ret_val = call_vsscanf("abc123", "abc %s", buffer);
27 ASSERT_EQ(ret_val, 1);
28 ASSERT_STREQ(buffer, "123");
29
30 ret_val = call_vsscanf("abc123", "%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("abc 123", "%3s%3s", buffer, buffer2);
36 ASSERT_EQ(ret_val, 2);
37 ASSERT_STREQ(buffer, "abc");
38 ASSERT_STREQ(buffer2, "123");
39 }
40
TEST(LlvmLibcVSScanfTest,IntConvSimple)41 TEST(LlvmLibcVSScanfTest, IntConvSimple) {
42 int ret_val;
43 int result = 0;
44 ret_val = call_vsscanf("123", "%d", &result);
45 EXPECT_EQ(ret_val, 1);
46 EXPECT_EQ(result, 123);
47
48 ret_val = call_vsscanf("456", "%i", &result);
49 EXPECT_EQ(ret_val, 1);
50 EXPECT_EQ(result, 456);
51
52 ret_val = call_vsscanf("789", "%x", &result);
53 EXPECT_EQ(ret_val, 1);
54 EXPECT_EQ(result, 0x789);
55
56 ret_val = call_vsscanf("012", "%o", &result);
57 EXPECT_EQ(ret_val, 1);
58 EXPECT_EQ(result, 012);
59
60 ret_val = call_vsscanf("345", "%u", &result);
61 EXPECT_EQ(ret_val, 1);
62 EXPECT_EQ(result, 345);
63
64 // 288 characters
65 ret_val = call_vsscanf("10000000000000000000000000000000"
66 "00000000000000000000000000000000"
67 "00000000000000000000000000000000"
68 "00000000000000000000000000000000"
69 "00000000000000000000000000000000"
70 "00000000000000000000000000000000"
71 "00000000000000000000000000000000"
72 "00000000000000000000000000000000"
73 "00000000000000000000000000000000",
74 "%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("Not an integer", "%d", &result);
79 EXPECT_EQ(ret_val, 0);
80 }
81
TEST(LlvmLibcVSScanfTest,IntConvLengthModifier)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("-1", "%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("8589967360", "%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("-8589967360", "%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("25", "%hhd", &char_result);
137 EXPECT_EQ(ret_val, 1);
138 EXPECT_EQ(char_result, char(25));
139 }
140
TEST(LlvmLibcVSScanfTest,IntConvBaseSelection)141 TEST(LlvmLibcVSScanfTest, IntConvBaseSelection) {
142 int ret_val;
143 int result = 0;
144 ret_val = call_vsscanf("0xabc123", "%i", &result);
145 EXPECT_EQ(ret_val, 1);
146 EXPECT_EQ(result, 0xabc123);
147
148 ret_val = call_vsscanf("0456", "%i", &result);
149 EXPECT_EQ(ret_val, 1);
150 EXPECT_EQ(result, 0456);
151
152 ret_val = call_vsscanf("0999", "%i", &result);
153 EXPECT_EQ(ret_val, 1);
154 EXPECT_EQ(result, 0);
155
156 ret_val = call_vsscanf("123abc456", "%i", &result);
157 EXPECT_EQ(ret_val, 1);
158 EXPECT_EQ(result, 123);
159 }
160