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 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 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 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 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 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 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 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 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