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