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 
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 
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 
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(1));
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 
148 static char int_to_b36_char(int input) {
149   if (input < 0 || input > 36)
150     return '0';
151   if (input < 10)
152     return static_cast<char>('0' + input);
153   return static_cast<char>('A' + input - 10);
154 }
155 
156 TEST(LlvmLibcStrToLTest, DecodeInOtherBases) {
157   char small_string[4] = {'\0', '\0', '\0', '\0'};
158   for (int base = 2; base <= 36; ++base) {
159     for (int first_digit = 0; first_digit <= 36; ++first_digit) {
160       small_string[0] = int_to_b36_char(first_digit);
161       if (first_digit < base) {
162         errno = 0;
163         ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
164                   static_cast<long int>(first_digit));
165         ASSERT_EQ(errno, 0);
166       } else {
167         errno = 0;
168         ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
169         ASSERT_EQ(errno, 0);
170       }
171     }
172   }
173 
174   for (int base = 2; base <= 36; ++base) {
175     for (int first_digit = 0; first_digit <= 36; ++first_digit) {
176       small_string[0] = int_to_b36_char(first_digit);
177       for (int second_digit = 0; second_digit <= 36; ++second_digit) {
178         small_string[1] = int_to_b36_char(second_digit);
179         if (first_digit < base && second_digit < base) {
180           errno = 0;
181           ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
182                     static_cast<long int>(second_digit + (first_digit * base)));
183           ASSERT_EQ(errno, 0);
184         } else if (first_digit < base) {
185           errno = 0;
186           ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
187                     static_cast<long int>(first_digit));
188           ASSERT_EQ(errno, 0);
189         } else {
190           errno = 0;
191           ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
192           ASSERT_EQ(errno, 0);
193         }
194       }
195     }
196   }
197 
198   for (int base = 2; base <= 36; ++base) {
199     for (int first_digit = 0; first_digit <= 36; ++first_digit) {
200       small_string[0] = int_to_b36_char(first_digit);
201       for (int second_digit = 0; second_digit <= 36; ++second_digit) {
202         small_string[1] = int_to_b36_char(second_digit);
203         for (int third_digit = 0; third_digit <= 36; ++third_digit) {
204           small_string[2] = int_to_b36_char(third_digit);
205 
206           if (first_digit < base && second_digit < base && third_digit < base) {
207             errno = 0;
208             ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
209                       static_cast<long int>(third_digit +
210                                             (second_digit * base) +
211                                             (first_digit * base * base)));
212             ASSERT_EQ(errno, 0);
213           } else if (first_digit < base && second_digit < base) {
214             errno = 0;
215             ASSERT_EQ(
216                 __llvm_libc::strtol(small_string, nullptr, base),
217                 static_cast<long int>(second_digit + (first_digit * base)));
218             ASSERT_EQ(errno, 0);
219           } else if (first_digit < base) {
220             // if the base is 16 there is a special case for the prefix 0X.
221             // The number is treated as a one digit hexadecimal.
222             if (base == 16 && first_digit == 0 && second_digit == 33) {
223               if (third_digit < base) {
224                 errno = 0;
225                 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
226                           static_cast<long int>(third_digit));
227                 ASSERT_EQ(errno, 0);
228               } else {
229                 errno = 0;
230                 ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
231                 ASSERT_EQ(errno, 0);
232               }
233             } else {
234               errno = 0;
235               ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base),
236                         static_cast<long int>(first_digit));
237               ASSERT_EQ(errno, 0);
238             }
239           } else {
240             errno = 0;
241             ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l);
242             ASSERT_EQ(errno, 0);
243           }
244         }
245       }
246     }
247   }
248 }
249 
250 TEST(LlvmLibcStrToLTest, CleanBaseSixteenDecode) {
251   char *str_end = nullptr;
252 
253   const char *no_prefix = "123abc";
254   errno = 0;
255   ASSERT_EQ(__llvm_libc::strtol(no_prefix, &str_end, 16), 0x123abcl);
256   ASSERT_EQ(errno, 0);
257   EXPECT_EQ(str_end - no_prefix, ptrdiff_t(6));
258 
259   const char *yes_prefix = "0x456def";
260   errno = 0;
261   ASSERT_EQ(__llvm_libc::strtol(yes_prefix, &str_end, 16), 0x456defl);
262   ASSERT_EQ(errno, 0);
263   EXPECT_EQ(str_end - yes_prefix, ptrdiff_t(8));
264 }
265 
266 TEST(LlvmLibcStrToLTest, AutomaticBaseSelection) {
267   char *str_end = nullptr;
268 
269   const char *base_ten = "12345";
270   errno = 0;
271   ASSERT_EQ(__llvm_libc::strtol(base_ten, &str_end, 0), 12345l);
272   ASSERT_EQ(errno, 0);
273   EXPECT_EQ(str_end - base_ten, ptrdiff_t(5));
274 
275   const char *base_sixteen_no_prefix = "123abc";
276   errno = 0;
277   ASSERT_EQ(__llvm_libc::strtol(base_sixteen_no_prefix, &str_end, 0), 123l);
278   ASSERT_EQ(errno, 0);
279   EXPECT_EQ(str_end - base_sixteen_no_prefix, ptrdiff_t(3));
280 
281   const char *base_sixteen_with_prefix = "0x456def";
282   errno = 0;
283   ASSERT_EQ(__llvm_libc::strtol(base_sixteen_with_prefix, &str_end, 0),
284             0x456defl);
285   ASSERT_EQ(errno, 0);
286   EXPECT_EQ(str_end - base_sixteen_with_prefix, ptrdiff_t(8));
287 
288   const char *base_eight_with_prefix = "012345";
289   errno = 0;
290   ASSERT_EQ(__llvm_libc::strtol(base_eight_with_prefix, &str_end, 0), 012345l);
291   ASSERT_EQ(errno, 0);
292   EXPECT_EQ(str_end - base_eight_with_prefix, ptrdiff_t(6));
293 }
294