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