1 //===-- Unittests for strtol ---------------------------------------------===//
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/stdlib/strtol.h"
10
11 #include "utils/UnitTest/Test.h"
12
13 #include <errno.h>
14 #include <limits.h>
15 #include <stddef.h>
16
TEST(LlvmLibcStrToLTest,InvalidBase)17 TEST(LlvmLibcStrToLTest, InvalidBase) {
18 const char *ten = "10";
19 errno = 0;
20 ASSERT_EQ(__llvm_libc::strtol(ten, nullptr, -1), 0l);
21 ASSERT_EQ(errno, EINVAL);
22 }
23
TEST(LlvmLibcStrToLTest,CleanBaseTenDecode)24 TEST(LlvmLibcStrToLTest, CleanBaseTenDecode) {
25 char *str_end = nullptr;
26
27 const char *ten = "10";
28 errno = 0;
29 ASSERT_EQ(__llvm_libc::strtol(ten, &str_end, 10), 10l);
30 ASSERT_EQ(errno, 0);
31 EXPECT_EQ(str_end - ten, ptrdiff_t(2));
32
33 errno = 0;
34 ASSERT_EQ(__llvm_libc::strtol(ten, nullptr, 10), 10l);
35 ASSERT_EQ(errno, 0);
36
37 const char *hundred = "100";
38 errno = 0;
39 ASSERT_EQ(__llvm_libc::strtol(hundred, &str_end, 10), 100l);
40 ASSERT_EQ(errno, 0);
41 EXPECT_EQ(str_end - hundred, ptrdiff_t(3));
42
43 const char *negative = "-100";
44 errno = 0;
45 ASSERT_EQ(__llvm_libc::strtol(negative, &str_end, 10), -100l);
46 ASSERT_EQ(errno, 0);
47 EXPECT_EQ(str_end - negative, ptrdiff_t(4));
48
49 const char *big_number = "1234567890";
50 errno = 0;
51 ASSERT_EQ(__llvm_libc::strtol(big_number, &str_end, 10), 1234567890l);
52 ASSERT_EQ(errno, 0);
53 EXPECT_EQ(str_end - big_number, ptrdiff_t(10));
54
55 const char *big_negative_number = "-1234567890";
56 errno = 0;
57 ASSERT_EQ(__llvm_libc::strtol(big_negative_number, &str_end, 10),
58 -1234567890l);
59 ASSERT_EQ(errno, 0);
60 EXPECT_EQ(str_end - big_negative_number, ptrdiff_t(11));
61
62 const char *too_big_number = "123456789012345678901";
63 errno = 0;
64 ASSERT_EQ(__llvm_libc::strtol(too_big_number, &str_end, 10), LONG_MAX);
65 ASSERT_EQ(errno, ERANGE);
66 EXPECT_EQ(str_end - too_big_number, ptrdiff_t(21));
67
68 const char *too_big_negative_number = "-123456789012345678901";
69 errno = 0;
70 ASSERT_EQ(__llvm_libc::strtol(too_big_negative_number, &str_end, 10),
71 LONG_MIN);
72 ASSERT_EQ(errno, ERANGE);
73 EXPECT_EQ(str_end - too_big_negative_number, ptrdiff_t(22));
74
75 const char *long_number_range_test =
76 "10000000000000000000000000000000000000000000000000";
77 errno = 0;
78 ASSERT_EQ(__llvm_libc::strtol(long_number_range_test, &str_end, 10),
79 LONG_MAX);
80 ASSERT_EQ(errno, ERANGE);
81 EXPECT_EQ(str_end - long_number_range_test, ptrdiff_t(50));
82 }
83
TEST(LlvmLibcStrToLTest,MessyBaseTenDecode)84 TEST(LlvmLibcStrToLTest, MessyBaseTenDecode) {
85 char *str_end = nullptr;
86
87 const char *spaces_before = " 10";
88 errno = 0;
89 ASSERT_EQ(__llvm_libc::strtol(spaces_before, &str_end, 10), 10l);
90 ASSERT_EQ(errno, 0);
91 EXPECT_EQ(str_end - spaces_before, ptrdiff_t(7));
92
93 const char *spaces_after = "10 ";
94 errno = 0;
95 ASSERT_EQ(__llvm_libc::strtol(spaces_after, &str_end, 10), 10l);
96 ASSERT_EQ(errno, 0);
97 EXPECT_EQ(str_end - spaces_after, ptrdiff_t(2));
98
99 const char *word_before = "word10";
100 errno = 0;
101 ASSERT_EQ(__llvm_libc::strtol(word_before, &str_end, 10), 0l);
102 ASSERT_EQ(errno, 0);
103 EXPECT_EQ(str_end - word_before, ptrdiff_t(0));
104
105 const char *word_after = "10word";
106 errno = 0;
107 ASSERT_EQ(__llvm_libc::strtol(word_after, &str_end, 10), 10l);
108 ASSERT_EQ(errno, 0);
109 EXPECT_EQ(str_end - word_after, ptrdiff_t(2));
110
111 const char *two_numbers = "10 999";
112 errno = 0;
113 ASSERT_EQ(__llvm_libc::strtol(two_numbers, &str_end, 10), 10l);
114 ASSERT_EQ(errno, 0);
115 EXPECT_EQ(str_end - two_numbers, ptrdiff_t(2));
116
117 const char *two_signs = "--10 999";
118 errno = 0;
119 ASSERT_EQ(__llvm_libc::strtol(two_signs, &str_end, 10), 0l);
120 ASSERT_EQ(errno, 0);
121 EXPECT_EQ(str_end - two_signs, ptrdiff_t(0));
122
123 const char *sign_before = "+2=4";
124 errno = 0;
125 ASSERT_EQ(__llvm_libc::strtol(sign_before, &str_end, 10), 2l);
126 ASSERT_EQ(errno, 0);
127 EXPECT_EQ(str_end - sign_before, ptrdiff_t(2));
128
129 const char *sign_after = "2+2=4";
130 errno = 0;
131 ASSERT_EQ(__llvm_libc::strtol(sign_after, &str_end, 10), 2l);
132 ASSERT_EQ(errno, 0);
133 EXPECT_EQ(str_end - sign_after, ptrdiff_t(1));
134
135 const char *tab_before = "\t10";
136 errno = 0;
137 ASSERT_EQ(__llvm_libc::strtol(tab_before, &str_end, 10), 10l);
138 ASSERT_EQ(errno, 0);
139 EXPECT_EQ(str_end - tab_before, ptrdiff_t(3));
140
141 const char *all_together = "\t -12345and+67890";
142 errno = 0;
143 ASSERT_EQ(__llvm_libc::strtol(all_together, &str_end, 10), -12345l);
144 ASSERT_EQ(errno, 0);
145 EXPECT_EQ(str_end - all_together, ptrdiff_t(9));
146
147 const char *just_spaces = " ";
148 errno = 0;
149 ASSERT_EQ(__llvm_libc::strtol(just_spaces, &str_end, 10), 0l);
150 ASSERT_EQ(errno, 0);
151 EXPECT_EQ(str_end - just_spaces, ptrdiff_t(0));
152
153 const char *just_space_and_sign = " +";
154 errno = 0;
155 ASSERT_EQ(__llvm_libc::strtol(just_space_and_sign, &str_end, 10), 0l);
156 ASSERT_EQ(errno, 0);
157 EXPECT_EQ(str_end - just_space_and_sign, ptrdiff_t(0));
158 }
159
int_to_b36_char(int input)160 static char int_to_b36_char(int input) {
161 if (input < 0 || input > 36)
162 return '0';
163 if (input < 10)
164 return static_cast<char>('0' + input);
165 return static_cast<char>('A' + input - 10);
166 }
167
TEST(LlvmLibcStrToLTest,DecodeInOtherBases)168 TEST(LlvmLibcStrToLTest, DecodeInOtherBases) {
169 char small_string[4] = {'\0', '\0', '\0', '\0'};
170 for (int base = 2; base <= 36; ++base) {
171 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
172 small_string[0] = int_to_b36_char(first_digit);
173 if (first_digit < base) {
174 errno = 0;
175 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
176 static_cast<long int>(first_digit));
177 ASSERT_EQ(errno, 0);
178 } else {
179 errno = 0;
180 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
181 ASSERT_EQ(errno, 0);
182 }
183 }
184 }
185
186 for (int base = 2; base <= 36; ++base) {
187 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
188 small_string[0] = int_to_b36_char(first_digit);
189 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
190 small_string[1] = int_to_b36_char(second_digit);
191 if (first_digit < base && second_digit < base) {
192 errno = 0;
193 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
194 static_cast<long int>(second_digit + (first_digit * base)));
195 ASSERT_EQ(errno, 0);
196 } else if (first_digit < base) {
197 errno = 0;
198 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
199 static_cast<long int>(first_digit));
200 ASSERT_EQ(errno, 0);
201 } else {
202 errno = 0;
203 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
204 ASSERT_EQ(errno, 0);
205 }
206 }
207 }
208 }
209
210 for (int base = 2; base <= 36; ++base) {
211 for (int first_digit = 0; first_digit <= 36; ++first_digit) {
212 small_string[0] = int_to_b36_char(first_digit);
213 for (int second_digit = 0; second_digit <= 36; ++second_digit) {
214 small_string[1] = int_to_b36_char(second_digit);
215 for (int third_digit = 0; third_digit <= 36; ++third_digit) {
216 small_string[2] = int_to_b36_char(third_digit);
217
218 if (first_digit < base && second_digit < base && third_digit < base) {
219 errno = 0;
220 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
221 static_cast<long int>(third_digit +
222 (second_digit * base) +
223 (first_digit * base * base)));
224 ASSERT_EQ(errno, 0);
225 } else if (first_digit < base && second_digit < base) {
226 errno = 0;
227 ASSERT_EQ(
228 __llvm_libc::strtol(small_string, nullptr, base),
229 static_cast<long int>(second_digit + (first_digit * base)));
230 ASSERT_EQ(errno, 0);
231 } else if (first_digit < base) {
232 // if the base is 16 there is a special case for the prefix 0X.
233 // The number is treated as a one digit hexadecimal.
234 if (base == 16 && first_digit == 0 && second_digit == 33) {
235 if (third_digit < base) {
236 errno = 0;
237 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
238 static_cast<long int>(third_digit));
239 ASSERT_EQ(errno, 0);
240 } else {
241 errno = 0;
242 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
243 ASSERT_EQ(errno, 0);
244 }
245 } else {
246 errno = 0;
247 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
248 static_cast<long int>(first_digit));
249 ASSERT_EQ(errno, 0);
250 }
251 } else {
252 errno = 0;
253 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
254 ASSERT_EQ(errno, 0);
255 }
256 }
257 }
258 }
259 }
260 }
261
TEST(LlvmLibcStrToLTest,CleanBaseSixteenDecode)262 TEST(LlvmLibcStrToLTest, CleanBaseSixteenDecode) {
263 char *str_end = nullptr;
264
265 const char *no_prefix = "123abc";
266 errno = 0;
267 ASSERT_EQ(__llvm_libc::strtol(no_prefix, &str_end, 16), 0x123abcl);
268 ASSERT_EQ(errno, 0);
269 EXPECT_EQ(str_end - no_prefix, ptrdiff_t(6));
270
271 const char *yes_prefix = "0x456def";
272 errno = 0;
273 ASSERT_EQ(__llvm_libc::strtol(yes_prefix, &str_end, 16), 0x456defl);
274 ASSERT_EQ(errno, 0);
275 EXPECT_EQ(str_end - yes_prefix, ptrdiff_t(8));
276
277 const char *letter_after_prefix = "0xabc123";
278 errno = 0;
279 ASSERT_EQ(__llvm_libc::strtol(letter_after_prefix, &str_end, 16), 0xabc123l);
280 ASSERT_EQ(errno, 0);
281 EXPECT_EQ(str_end - letter_after_prefix, ptrdiff_t(8));
282 }
283
TEST(LlvmLibcStrToLTest,MessyBaseSixteenDecode)284 TEST(LlvmLibcStrToLTest, MessyBaseSixteenDecode) {
285 char *str_end = nullptr;
286
287 const char *just_prefix = "0x";
288 errno = 0;
289 ASSERT_EQ(__llvm_libc::strtol(just_prefix, &str_end, 16), 0l);
290 ASSERT_EQ(errno, 0);
291 EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
292
293 errno = 0;
294 ASSERT_EQ(__llvm_libc::strtol(just_prefix, &str_end, 0), 0l);
295 ASSERT_EQ(errno, 0);
296 EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
297
298 const char *prefix_with_x_after = "0xx";
299 errno = 0;
300 ASSERT_EQ(__llvm_libc::strtol(prefix_with_x_after, &str_end, 16), 0l);
301 ASSERT_EQ(errno, 0);
302 EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
303
304 errno = 0;
305 ASSERT_EQ(__llvm_libc::strtol(prefix_with_x_after, &str_end, 0), 0l);
306 ASSERT_EQ(errno, 0);
307 EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
308 }
309
TEST(LlvmLibcStrToLTest,AutomaticBaseSelection)310 TEST(LlvmLibcStrToLTest, AutomaticBaseSelection) {
311 char *str_end = nullptr;
312
313 const char *base_ten = "12345";
314 errno = 0;
315 ASSERT_EQ(__llvm_libc::strtol(base_ten, &str_end, 0), 12345l);
316 ASSERT_EQ(errno, 0);
317 EXPECT_EQ(str_end - base_ten, ptrdiff_t(5));
318
319 const char *base_sixteen_no_prefix = "123abc";
320 errno = 0;
321 ASSERT_EQ(__llvm_libc::strtol(base_sixteen_no_prefix, &str_end, 0), 123l);
322 ASSERT_EQ(errno, 0);
323 EXPECT_EQ(str_end - base_sixteen_no_prefix, ptrdiff_t(3));
324
325 const char *base_sixteen_with_prefix = "0x456def";
326 errno = 0;
327 ASSERT_EQ(__llvm_libc::strtol(base_sixteen_with_prefix, &str_end, 0),
328 0x456defl);
329 ASSERT_EQ(errno, 0);
330 EXPECT_EQ(str_end - base_sixteen_with_prefix, ptrdiff_t(8));
331
332 const char *base_eight_with_prefix = "012345";
333 errno = 0;
334 ASSERT_EQ(__llvm_libc::strtol(base_eight_with_prefix, &str_end, 0), 012345l);
335 ASSERT_EQ(errno, 0);
336 EXPECT_EQ(str_end - base_eight_with_prefix, ptrdiff_t(6));
337
338 const char *just_zero = "0";
339 errno = 0;
340 ASSERT_EQ(__llvm_libc::strtol(just_zero, &str_end, 0), 0l);
341 ASSERT_EQ(errno, 0);
342 EXPECT_EQ(str_end - just_zero, ptrdiff_t(1));
343
344 const char *just_zero_x = "0x";
345 errno = 0;
346 ASSERT_EQ(__llvm_libc::strtol(just_zero_x, &str_end, 0), 0l);
347 ASSERT_EQ(errno, 0);
348 EXPECT_EQ(str_end - just_zero_x, ptrdiff_t(1));
349
350 const char *just_zero_eight = "08";
351 errno = 0;
352 ASSERT_EQ(__llvm_libc::strtol(just_zero_eight, &str_end, 0), 0l);
353 ASSERT_EQ(errno, 0);
354 EXPECT_EQ(str_end - just_zero_eight, ptrdiff_t(1));
355 }
356