1 //===-- Unittests for strtoull --------------------------------------------===//
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/strtoull.h"
10 
11 #include <errno.h>
12 #include <limits.h>
13 #include <stddef.h>
14 
15 #include "utils/UnitTest/Test.h"
16 
TEST(LlvmLibcStrToULLTest,InvalidBase)17 TEST(LlvmLibcStrToULLTest, InvalidBase) {
18   const char *ten = "10";
19   errno = 0;
20   ASSERT_EQ(__llvm_libc::strtoull(ten, nullptr, -1), 0ull);
21   ASSERT_EQ(errno, EINVAL);
22 }
23 
TEST(LlvmLibcStrToULLTest,CleanBaseTenDecode)24 TEST(LlvmLibcStrToULLTest, CleanBaseTenDecode) {
25   char *str_end = nullptr;
26 
27   const char *ten = "10";
28   errno = 0;
29   ASSERT_EQ(__llvm_libc::strtoull(ten, &str_end, 10), 10ull);
30   ASSERT_EQ(errno, 0);
31   EXPECT_EQ(str_end - ten, ptrdiff_t(2));
32   errno = 0;
33   ASSERT_EQ(__llvm_libc::strtoull(ten, nullptr, 10), 10ull);
34   ASSERT_EQ(errno, 0);
35 
36   const char *hundred = "100";
37   errno = 0;
38   ASSERT_EQ(__llvm_libc::strtoull(hundred, &str_end, 10), 100ull);
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::strtoull(negative, &str_end, 10), -(100ull));
45   ASSERT_EQ(errno, 0);
46   EXPECT_EQ(str_end - negative, ptrdiff_t(4));
47 
48   const char *big_number = "123456789012345";
49   errno = 0;
50   ASSERT_EQ(__llvm_libc::strtoull(big_number, &str_end, 10),
51             123456789012345ull);
52   ASSERT_EQ(errno, 0);
53   EXPECT_EQ(str_end - big_number, ptrdiff_t(15));
54 
55   const char *unsigned_long_long_max_number = "18446744073709551615";
56   errno = 0;
57   ASSERT_EQ(__llvm_libc::strtoull(unsigned_long_long_max_number, &str_end, 10),
58             18446744073709551615ull);
59   ASSERT_EQ(errno, 0);
60   EXPECT_EQ(str_end - unsigned_long_long_max_number, ptrdiff_t(20));
61 
62   const char *too_big_number = "123456789012345678901";
63   errno = 0;
64   ASSERT_EQ(__llvm_libc::strtoull(too_big_number, &str_end, 10), ULLONG_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::strtoull(too_big_negative_number, &str_end, 10),
71             ULLONG_MAX);
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::strtoull(long_number_range_test, &str_end, 10),
79             ULLONG_MAX);
80   ASSERT_EQ(errno, ERANGE);
81   EXPECT_EQ(str_end - long_number_range_test, ptrdiff_t(50));
82 }
83 
TEST(LlvmLibcStrToULLTest,MessyBaseTenDecode)84 TEST(LlvmLibcStrToULLTest, MessyBaseTenDecode) {
85   char *str_end = nullptr;
86 
87   const char *spaces_before = "     10";
88   errno = 0;
89   ASSERT_EQ(__llvm_libc::strtoull(spaces_before, &str_end, 10), 10ull);
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::strtoull(spaces_after, &str_end, 10), 10ull);
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::strtoull(word_before, &str_end, 10), 0ull);
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::strtoull(word_after, &str_end, 10), 10ull);
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::strtoull(two_numbers, &str_end, 10), 10ull);
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::strtoull(two_signs, &str_end, 10), 0ull);
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::strtoull(sign_before, &str_end, 10), 2ull);
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::strtoull(sign_after, &str_end, 10), 2ull);
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::strtoull(tab_before, &str_end, 10), 10ull);
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::strtoull(all_together, &str_end, 10), -(12345ull));
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::strtoull(just_spaces, &str_end, 10), 0ull);
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::strtoull(just_space_and_sign, &str_end, 10), 0ull);
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(LlvmLibcStrToULLTest,DecodeInOtherBases)168 TEST(LlvmLibcStrToULLTest, 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::strtoull(small_string, nullptr, base),
176                   static_cast<unsigned long long int>(first_digit));
177         ASSERT_EQ(errno, 0);
178       } else {
179         errno = 0;
180         ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull);
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::strtoull(small_string, nullptr, base),
194                     static_cast<unsigned long long int>(second_digit +
195                                                         (first_digit * base)));
196           ASSERT_EQ(errno, 0);
197         } else if (first_digit < base) {
198           errno = 0;
199           ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
200                     static_cast<unsigned long long int>(first_digit));
201           ASSERT_EQ(errno, 0);
202         } else {
203           errno = 0;
204           ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull);
205           ASSERT_EQ(errno, 0);
206         }
207       }
208     }
209   }
210 
211   for (int base = 2; base <= 36; ++base) {
212     for (int first_digit = 0; first_digit <= 36; ++first_digit) {
213       small_string[0] = int_to_b36_char(first_digit);
214       for (int second_digit = 0; second_digit <= 36; ++second_digit) {
215         small_string[1] = int_to_b36_char(second_digit);
216         for (int third_digit = 0; third_digit <= 36; ++third_digit) {
217           small_string[2] = int_to_b36_char(third_digit);
218 
219           if (first_digit < base && second_digit < base && third_digit < base) {
220             errno = 0;
221             ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
222                       static_cast<unsigned long long int>(
223                           third_digit + (second_digit * base) +
224                           (first_digit * base * base)));
225             ASSERT_EQ(errno, 0);
226           } else if (first_digit < base && second_digit < base) {
227             errno = 0;
228             ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
229                       static_cast<unsigned long long int>(
230                           second_digit + (first_digit * base)));
231             ASSERT_EQ(errno, 0);
232           } else if (first_digit < base) {
233             // if the base is 16 there is a special case for the prefix 0X.
234             // The number is treated as a one digit hexadecimal.
235             if (base == 16 && first_digit == 0 && second_digit == 33) {
236               if (third_digit < base) {
237                 errno = 0;
238                 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
239                           static_cast<unsigned long long int>(third_digit));
240                 ASSERT_EQ(errno, 0);
241               } else {
242                 errno = 0;
243                 ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
244                           0ull);
245                 ASSERT_EQ(errno, 0);
246               }
247             } else {
248               errno = 0;
249               ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base),
250                         static_cast<unsigned long long int>(first_digit));
251               ASSERT_EQ(errno, 0);
252             }
253           } else {
254             errno = 0;
255             ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull);
256             ASSERT_EQ(errno, 0);
257           }
258         }
259       }
260     }
261   }
262 }
263 
TEST(LlvmLibcStrToULLTest,CleanBaseSixteenDecode)264 TEST(LlvmLibcStrToULLTest, CleanBaseSixteenDecode) {
265   char *str_end = nullptr;
266 
267   const char *no_prefix = "123abc";
268   errno = 0;
269   ASSERT_EQ(__llvm_libc::strtoull(no_prefix, &str_end, 16), 0x123abcull);
270   ASSERT_EQ(errno, 0);
271   EXPECT_EQ(str_end - no_prefix, ptrdiff_t(6));
272 
273   const char *yes_prefix = "0x456def";
274   errno = 0;
275   ASSERT_EQ(__llvm_libc::strtoull(yes_prefix, &str_end, 16), 0x456defull);
276   ASSERT_EQ(errno, 0);
277   EXPECT_EQ(str_end - yes_prefix, ptrdiff_t(8));
278 
279   const char *letter_after_prefix = "0xabc123";
280   errno = 0;
281   ASSERT_EQ(__llvm_libc::strtoull(letter_after_prefix, &str_end, 16),
282             0xabc123ull);
283   ASSERT_EQ(errno, 0);
284   EXPECT_EQ(str_end - letter_after_prefix, ptrdiff_t(8));
285 }
286 
TEST(LlvmLibcStrToULLTest,MessyBaseSixteenDecode)287 TEST(LlvmLibcStrToULLTest, MessyBaseSixteenDecode) {
288   char *str_end = nullptr;
289 
290   const char *just_prefix = "0x";
291   errno = 0;
292   ASSERT_EQ(__llvm_libc::strtoull(just_prefix, &str_end, 16), 0ull);
293   ASSERT_EQ(errno, 0);
294   EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
295 
296   errno = 0;
297   ASSERT_EQ(__llvm_libc::strtoull(just_prefix, &str_end, 0), 0ull);
298   ASSERT_EQ(errno, 0);
299   EXPECT_EQ(str_end - just_prefix, ptrdiff_t(1));
300 
301   const char *prefix_with_x_after = "0xx";
302   errno = 0;
303   ASSERT_EQ(__llvm_libc::strtoull(prefix_with_x_after, &str_end, 16), 0ull);
304   ASSERT_EQ(errno, 0);
305   EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
306 
307   errno = 0;
308   ASSERT_EQ(__llvm_libc::strtoull(prefix_with_x_after, &str_end, 0), 0ull);
309   ASSERT_EQ(errno, 0);
310   EXPECT_EQ(str_end - prefix_with_x_after, ptrdiff_t(1));
311 }
312 
TEST(LlvmLibcStrToULLTest,AutomaticBaseSelection)313 TEST(LlvmLibcStrToULLTest, AutomaticBaseSelection) {
314   char *str_end = nullptr;
315 
316   const char *base_ten = "12345";
317   errno = 0;
318   ASSERT_EQ(__llvm_libc::strtoull(base_ten, &str_end, 0), 12345ull);
319   ASSERT_EQ(errno, 0);
320   EXPECT_EQ(str_end - base_ten, ptrdiff_t(5));
321 
322   const char *base_sixteen_no_prefix = "123abc";
323   errno = 0;
324   ASSERT_EQ(__llvm_libc::strtoull(base_sixteen_no_prefix, &str_end, 0), 123ull);
325   ASSERT_EQ(errno, 0);
326   EXPECT_EQ(str_end - base_sixteen_no_prefix, ptrdiff_t(3));
327 
328   const char *base_sixteen_with_prefix = "0x456def";
329   errno = 0;
330   ASSERT_EQ(__llvm_libc::strtoull(base_sixteen_with_prefix, &str_end, 0),
331             0x456defull);
332   ASSERT_EQ(errno, 0);
333   EXPECT_EQ(str_end - base_sixteen_with_prefix, ptrdiff_t(8));
334 
335   const char *base_eight_with_prefix = "012345";
336   errno = 0;
337   ASSERT_EQ(__llvm_libc::strtoull(base_eight_with_prefix, &str_end, 0),
338             012345ull);
339   ASSERT_EQ(errno, 0);
340   EXPECT_EQ(str_end - base_eight_with_prefix, ptrdiff_t(6));
341 
342   const char *just_zero = "0";
343   errno = 0;
344   ASSERT_EQ(__llvm_libc::strtoull(just_zero, &str_end, 0), 0ull);
345   ASSERT_EQ(errno, 0);
346   EXPECT_EQ(str_end - just_zero, ptrdiff_t(1));
347 
348   const char *just_zero_x = "0x";
349   errno = 0;
350   ASSERT_EQ(__llvm_libc::strtoull(just_zero_x, &str_end, 0), 0ull);
351   ASSERT_EQ(errno, 0);
352   EXPECT_EQ(str_end - just_zero_x, ptrdiff_t(1));
353 
354   const char *just_zero_eight = "08";
355   errno = 0;
356   ASSERT_EQ(__llvm_libc::strtoull(just_zero_eight, &str_end, 0), 0ull);
357   ASSERT_EQ(errno, 0);
358   EXPECT_EQ(str_end - just_zero_eight, ptrdiff_t(1));
359 }
360