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