1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "base/strings/string_number_conversions.h"
11
12 #include <errno.h>
13 #include <limits.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <stdio.h>
17
18 #include <cmath>
19 #include <limits>
20 #include <string_view>
21
22 #include "base/bit_cast.h"
23 #include "base/format_macros.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 namespace base {
29
30 namespace {
31
32 template <typename INT>
33 struct NumberToStringTest {
34 INT num;
35 const char* sexpected;
36 const char* uexpected;
37 };
38
39 } // namespace
40
TEST(StringNumberConversionsTest,NumberToString)41 TEST(StringNumberConversionsTest, NumberToString) {
42 static const NumberToStringTest<int> int_tests[] = {
43 {0, "0", "0"},
44 {-1, "-1", "4294967295"},
45 {std::numeric_limits<int>::max(), "2147483647", "2147483647"},
46 {std::numeric_limits<int>::min(), "-2147483648", "2147483648"},
47 };
48 static const NumberToStringTest<int64_t> int64_tests[] = {
49 {0, "0", "0"},
50 {-1, "-1", "18446744073709551615"},
51 {
52 std::numeric_limits<int64_t>::max(),
53 "9223372036854775807",
54 "9223372036854775807",
55 },
56 {std::numeric_limits<int64_t>::min(), "-9223372036854775808",
57 "9223372036854775808"},
58 };
59
60 for (const auto& test : int_tests) {
61 EXPECT_EQ(NumberToString(test.num), test.sexpected);
62 EXPECT_EQ(NumberToString16(test.num), UTF8ToUTF16(test.sexpected));
63 EXPECT_EQ(NumberToString(static_cast<unsigned>(test.num)), test.uexpected);
64 EXPECT_EQ(NumberToString16(static_cast<unsigned>(test.num)),
65 UTF8ToUTF16(test.uexpected));
66 }
67 for (const auto& test : int64_tests) {
68 EXPECT_EQ(NumberToString(test.num), test.sexpected);
69 EXPECT_EQ(NumberToString16(test.num), UTF8ToUTF16(test.sexpected));
70 EXPECT_EQ(NumberToString(static_cast<uint64_t>(test.num)), test.uexpected);
71 EXPECT_EQ(NumberToString16(static_cast<uint64_t>(test.num)),
72 UTF8ToUTF16(test.uexpected));
73 }
74 }
75
TEST(StringNumberConversionsTest,Uint64ToString)76 TEST(StringNumberConversionsTest, Uint64ToString) {
77 static const struct {
78 uint64_t input;
79 std::string output;
80 } cases[] = {
81 {0, "0"},
82 {42, "42"},
83 {INT_MAX, "2147483647"},
84 {std::numeric_limits<uint64_t>::max(), "18446744073709551615"},
85 };
86
87 for (const auto& i : cases)
88 EXPECT_EQ(i.output, NumberToString(i.input));
89 }
90
TEST(StringNumberConversionsTest,SizeTToString)91 TEST(StringNumberConversionsTest, SizeTToString) {
92 size_t size_t_max = std::numeric_limits<size_t>::max();
93 std::string size_t_max_string = StringPrintf("%" PRIuS, size_t_max);
94
95 static const struct {
96 size_t input;
97 std::string output;
98 } cases[] = {
99 {0, "0"},
100 {9, "9"},
101 {42, "42"},
102 {INT_MAX, "2147483647"},
103 {2147483648U, "2147483648"},
104 #if SIZE_MAX > 4294967295U
105 {99999999999U, "99999999999"},
106 #endif
107 {size_t_max, size_t_max_string},
108 };
109
110 for (const auto& i : cases)
111 EXPECT_EQ(i.output, NumberToString(i.input));
112 }
113
TEST(StringNumberConversionsTest,StringToInt)114 TEST(StringNumberConversionsTest, StringToInt) {
115 static const struct {
116 std::string input;
117 int output;
118 bool success;
119 } cases[] = {
120 {"0", 0, true},
121 {"42", 42, true},
122 {"42\x99", 42, false},
123 {"\x99"
124 "42\x99",
125 0, false},
126 {"-2147483648", INT_MIN, true},
127 {"2147483647", INT_MAX, true},
128 {"", 0, false},
129 {" 42", 42, false},
130 {"42 ", 42, false},
131 {"\t\n\v\f\r 42", 42, false},
132 {"blah42", 0, false},
133 {"42blah", 42, false},
134 {"blah42blah", 0, false},
135 {"-273.15", -273, false},
136 {"+98.6", 98, false},
137 {"--123", 0, false},
138 {"++123", 0, false},
139 {"-+123", 0, false},
140 {"+-123", 0, false},
141 {"-", 0, false},
142 {"-2147483649", INT_MIN, false},
143 {"-99999999999", INT_MIN, false},
144 {"2147483648", INT_MAX, false},
145 {"99999999999", INT_MAX, false},
146 };
147
148 for (const auto& i : cases) {
149 int output = i.output ^ 1; // Ensure StringToInt wrote something.
150 EXPECT_EQ(i.success, StringToInt(i.input, &output));
151 EXPECT_EQ(i.output, output);
152
153 std::u16string utf16_input = UTF8ToUTF16(i.input);
154 output = i.output ^ 1; // Ensure StringToInt wrote something.
155 EXPECT_EQ(i.success, StringToInt(utf16_input, &output));
156 EXPECT_EQ(i.output, output);
157 }
158
159 // One additional test to verify that conversion of numbers in strings with
160 // embedded NUL characters. The NUL and extra data after it should be
161 // interpreted as junk after the number.
162 const char input[] =
163 "6\0"
164 "6";
165 std::string input_string(input, std::size(input) - 1);
166 int output;
167 EXPECT_FALSE(StringToInt(input_string, &output));
168 EXPECT_EQ(6, output);
169
170 std::u16string utf16_input = UTF8ToUTF16(input_string);
171 output = 0;
172 EXPECT_FALSE(StringToInt(utf16_input, &output));
173 EXPECT_EQ(6, output);
174
175 output = 0;
176 const char16_t negative_wide_input[] = {0xFF4D, '4', '2', 0};
177 EXPECT_FALSE(StringToInt(std::u16string(negative_wide_input), &output));
178 EXPECT_EQ(0, output);
179 }
180
TEST(StringNumberConversionsTest,StringToUint)181 TEST(StringNumberConversionsTest, StringToUint) {
182 static const struct {
183 std::string input;
184 unsigned output;
185 bool success;
186 } cases[] = {
187 {"0", 0, true},
188 {"42", 42, true},
189 {"42\x99", 42, false},
190 {"\x99"
191 "42\x99",
192 0, false},
193 {"-2147483648", 0, false},
194 {"2147483647", INT_MAX, true},
195 {"", 0, false},
196 {" 42", 42, false},
197 {"42 ", 42, false},
198 {"\t\n\v\f\r 42", 42, false},
199 {"blah42", 0, false},
200 {"42blah", 42, false},
201 {"blah42blah", 0, false},
202 {"-273.15", 0, false},
203 {"+98.6", 98, false},
204 {"--123", 0, false},
205 {"++123", 0, false},
206 {"-+123", 0, false},
207 {"+-123", 0, false},
208 {"-", 0, false},
209 {"-2147483649", 0, false},
210 {"-99999999999", 0, false},
211 {"4294967295", UINT_MAX, true},
212 {"4294967296", UINT_MAX, false},
213 {"99999999999", UINT_MAX, false},
214 };
215
216 for (const auto& i : cases) {
217 unsigned output = i.output ^ 1; // Ensure StringToUint wrote something.
218 EXPECT_EQ(i.success, StringToUint(i.input, &output));
219 EXPECT_EQ(i.output, output);
220
221 std::u16string utf16_input = UTF8ToUTF16(i.input);
222 output = i.output ^ 1; // Ensure StringToUint wrote something.
223 EXPECT_EQ(i.success, StringToUint(utf16_input, &output));
224 EXPECT_EQ(i.output, output);
225 }
226
227 // One additional test to verify that conversion of numbers in strings with
228 // embedded NUL characters. The NUL and extra data after it should be
229 // interpreted as junk after the number.
230 const char input[] =
231 "6\0"
232 "6";
233 std::string input_string(input, std::size(input) - 1);
234 unsigned output;
235 EXPECT_FALSE(StringToUint(input_string, &output));
236 EXPECT_EQ(6U, output);
237
238 std::u16string utf16_input = UTF8ToUTF16(input_string);
239 output = 0;
240 EXPECT_FALSE(StringToUint(utf16_input, &output));
241 EXPECT_EQ(6U, output);
242
243 output = 0;
244 const char16_t negative_wide_input[] = {0xFF4D, '4', '2', 0};
245 EXPECT_FALSE(StringToUint(std::u16string(negative_wide_input), &output));
246 EXPECT_EQ(0U, output);
247 }
248
TEST(StringNumberConversionsTest,StringToInt64)249 TEST(StringNumberConversionsTest, StringToInt64) {
250 static const struct {
251 std::string input;
252 int64_t output;
253 bool success;
254 } cases[] = {
255 {"0", 0, true},
256 {"42", 42, true},
257 {"-2147483648", INT_MIN, true},
258 {"2147483647", INT_MAX, true},
259 {"-2147483649", INT64_C(-2147483649), true},
260 {"-99999999999", INT64_C(-99999999999), true},
261 {"2147483648", INT64_C(2147483648), true},
262 {"99999999999", INT64_C(99999999999), true},
263 {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
264 {"-9223372036854775808", std::numeric_limits<int64_t>::min(), true},
265 {"09", 9, true},
266 {"-09", -9, true},
267 {"", 0, false},
268 {" 42", 42, false},
269 {"42 ", 42, false},
270 {"0x42", 0, false},
271 {"\t\n\v\f\r 42", 42, false},
272 {"blah42", 0, false},
273 {"42blah", 42, false},
274 {"blah42blah", 0, false},
275 {"-273.15", -273, false},
276 {"+98.6", 98, false},
277 {"--123", 0, false},
278 {"++123", 0, false},
279 {"-+123", 0, false},
280 {"+-123", 0, false},
281 {"-", 0, false},
282 {"-9223372036854775809", std::numeric_limits<int64_t>::min(), false},
283 {"-99999999999999999999", std::numeric_limits<int64_t>::min(), false},
284 {"9223372036854775808", std::numeric_limits<int64_t>::max(), false},
285 {"99999999999999999999", std::numeric_limits<int64_t>::max(), false},
286 };
287
288 for (const auto& i : cases) {
289 int64_t output = 0;
290 EXPECT_EQ(i.success, StringToInt64(i.input, &output));
291 EXPECT_EQ(i.output, output);
292
293 std::u16string utf16_input = UTF8ToUTF16(i.input);
294 output = 0;
295 EXPECT_EQ(i.success, StringToInt64(utf16_input, &output));
296 EXPECT_EQ(i.output, output);
297 }
298
299 // One additional test to verify that conversion of numbers in strings with
300 // embedded NUL characters. The NUL and extra data after it should be
301 // interpreted as junk after the number.
302 const char input[] =
303 "6\0"
304 "6";
305 std::string input_string(input, std::size(input) - 1);
306 int64_t output;
307 EXPECT_FALSE(StringToInt64(input_string, &output));
308 EXPECT_EQ(6, output);
309
310 std::u16string utf16_input = UTF8ToUTF16(input_string);
311 output = 0;
312 EXPECT_FALSE(StringToInt64(utf16_input, &output));
313 EXPECT_EQ(6, output);
314 }
315
TEST(StringNumberConversionsTest,StringToUint64)316 TEST(StringNumberConversionsTest, StringToUint64) {
317 static const struct {
318 std::string input;
319 uint64_t output;
320 bool success;
321 } cases[] = {
322 {"0", 0, true},
323 {"42", 42, true},
324 {"-2147483648", 0, false},
325 {"2147483647", INT_MAX, true},
326 {"-2147483649", 0, false},
327 {"-99999999999", 0, false},
328 {"2147483648", UINT64_C(2147483648), true},
329 {"99999999999", UINT64_C(99999999999), true},
330 {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
331 {"-9223372036854775808", 0, false},
332 {"09", 9, true},
333 {"-09", 0, false},
334 {"", 0, false},
335 {" 42", 42, false},
336 {"42 ", 42, false},
337 {"0x42", 0, false},
338 {"\t\n\v\f\r 42", 42, false},
339 {"blah42", 0, false},
340 {"42blah", 42, false},
341 {"blah42blah", 0, false},
342 {"-273.15", 0, false},
343 {"+98.6", 98, false},
344 {"--123", 0, false},
345 {"++123", 0, false},
346 {"-+123", 0, false},
347 {"+-123", 0, false},
348 {"-", 0, false},
349 {"-9223372036854775809", 0, false},
350 {"-99999999999999999999", 0, false},
351 {"9223372036854775808", UINT64_C(9223372036854775808), true},
352 {"99999999999999999999", std::numeric_limits<uint64_t>::max(), false},
353 {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true},
354 {"18446744073709551616", std::numeric_limits<uint64_t>::max(), false},
355 };
356
357 for (const auto& i : cases) {
358 uint64_t output = 0;
359 EXPECT_EQ(i.success, StringToUint64(i.input, &output));
360 EXPECT_EQ(i.output, output);
361
362 std::u16string utf16_input = UTF8ToUTF16(i.input);
363 output = 0;
364 EXPECT_EQ(i.success, StringToUint64(utf16_input, &output));
365 EXPECT_EQ(i.output, output);
366 }
367
368 // One additional test to verify that conversion of numbers in strings with
369 // embedded NUL characters. The NUL and extra data after it should be
370 // interpreted as junk after the number.
371 const char input[] =
372 "6\0"
373 "6";
374 std::string input_string(input, std::size(input) - 1);
375 uint64_t output;
376 EXPECT_FALSE(StringToUint64(input_string, &output));
377 EXPECT_EQ(6U, output);
378
379 std::u16string utf16_input = UTF8ToUTF16(input_string);
380 output = 0;
381 EXPECT_FALSE(StringToUint64(utf16_input, &output));
382 EXPECT_EQ(6U, output);
383 }
384
TEST(StringNumberConversionsTest,StringToSizeT)385 TEST(StringNumberConversionsTest, StringToSizeT) {
386 size_t size_t_max = std::numeric_limits<size_t>::max();
387 std::string size_t_max_string = StringPrintf("%" PRIuS, size_t_max);
388
389 static const struct {
390 std::string input;
391 size_t output;
392 bool success;
393 } cases[] = {
394 {"0", 0, true},
395 {"42", 42, true},
396 {"-2147483648", 0, false},
397 {"2147483647", INT_MAX, true},
398 {"-2147483649", 0, false},
399 {"-99999999999", 0, false},
400 {"2147483648", 2147483648U, true},
401 #if SIZE_MAX > 4294967295U
402 {"99999999999", 99999999999U, true},
403 #endif
404 {"-9223372036854775808", 0, false},
405 {"09", 9, true},
406 {"-09", 0, false},
407 {"", 0, false},
408 {" 42", 42, false},
409 {"42 ", 42, false},
410 {"0x42", 0, false},
411 {"\t\n\v\f\r 42", 42, false},
412 {"blah42", 0, false},
413 {"42blah", 42, false},
414 {"blah42blah", 0, false},
415 {"-273.15", 0, false},
416 {"+98.6", 98, false},
417 {"--123", 0, false},
418 {"++123", 0, false},
419 {"-+123", 0, false},
420 {"+-123", 0, false},
421 {"-", 0, false},
422 {"-9223372036854775809", 0, false},
423 {"-99999999999999999999", 0, false},
424 {"999999999999999999999999", size_t_max, false},
425 {size_t_max_string, size_t_max, true},
426 };
427
428 for (const auto& i : cases) {
429 size_t output = 0;
430 EXPECT_EQ(i.success, StringToSizeT(i.input, &output));
431 EXPECT_EQ(i.output, output);
432
433 std::u16string utf16_input = UTF8ToUTF16(i.input);
434 output = 0;
435 EXPECT_EQ(i.success, StringToSizeT(utf16_input, &output));
436 EXPECT_EQ(i.output, output);
437 }
438
439 // One additional test to verify that conversion of numbers in strings with
440 // embedded NUL characters. The NUL and extra data after it should be
441 // interpreted as junk after the number.
442 const char input[] =
443 "6\0"
444 "6";
445 std::string input_string(input, std::size(input) - 1);
446 size_t output;
447 EXPECT_FALSE(StringToSizeT(input_string, &output));
448 EXPECT_EQ(6U, output);
449
450 std::u16string utf16_input = UTF8ToUTF16(input_string);
451 output = 0;
452 EXPECT_FALSE(StringToSizeT(utf16_input, &output));
453 EXPECT_EQ(6U, output);
454 }
455
TEST(StringNumberConversionsTest,HexStringToInt)456 TEST(StringNumberConversionsTest, HexStringToInt) {
457 static const struct {
458 std::string input;
459 int64_t output;
460 bool success;
461 } cases[] = {
462 {"0", 0, true},
463 {"42", 66, true},
464 {"-42", -66, true},
465 {"+42", 66, true},
466 {"7fffffff", INT_MAX, true},
467 {"-80000000", INT_MIN, true},
468 {"80000000", INT_MAX, false}, // Overflow test.
469 {"-80000001", INT_MIN, false}, // Underflow test.
470 {"0x42", 66, true},
471 {"-0x42", -66, true},
472 {"+0x42", 66, true},
473 {"0x7fffffff", INT_MAX, true},
474 {"-0x80000000", INT_MIN, true},
475 {"-80000000", INT_MIN, true},
476 {"80000000", INT_MAX, false}, // Overflow test.
477 {"-80000001", INT_MIN, false}, // Underflow test.
478 {"0x0f", 15, true},
479 {"0f", 15, true},
480 {" 45", 0x45, false},
481 {"\t\n\v\f\r 0x45", 0x45, false},
482 {" 45", 0x45, false},
483 {"45 ", 0x45, false},
484 {"45:", 0x45, false},
485 {"efgh", 0xef, false},
486 {"0xefgh", 0xef, false},
487 {"hgfe", 0, false},
488 {"-", 0, false},
489 {"", 0, false},
490 {"0x", 0, false},
491 };
492
493 for (const auto& i : cases) {
494 int output = 0;
495 EXPECT_EQ(i.success, HexStringToInt(i.input, &output));
496 EXPECT_EQ(i.output, output);
497 }
498 // One additional test to verify that conversion of numbers in strings with
499 // embedded NUL characters. The NUL and extra data after it should be
500 // interpreted as junk after the number.
501 const char input[] =
502 "0xc0ffee\0"
503 "9";
504 std::string input_string(input, std::size(input) - 1);
505 int output;
506 EXPECT_FALSE(HexStringToInt(input_string, &output));
507 EXPECT_EQ(0xc0ffee, output);
508 }
509
TEST(StringNumberConversionsTest,HexStringToUInt)510 TEST(StringNumberConversionsTest, HexStringToUInt) {
511 static const struct {
512 std::string input;
513 uint32_t output;
514 bool success;
515 } cases[] = {
516 {"0", 0, true},
517 {"42", 0x42, true},
518 {"-42", 0, false},
519 {"+42", 0x42, true},
520 {"7fffffff", INT_MAX, true},
521 {"-80000000", 0, false},
522 {"ffffffff", 0xffffffff, true},
523 {"DeadBeef", 0xdeadbeef, true},
524 {"0x42", 0x42, true},
525 {"-0x42", 0, false},
526 {"+0x42", 0x42, true},
527 {"0x7fffffff", INT_MAX, true},
528 {"-0x80000000", 0, false},
529 {"0xffffffff", std::numeric_limits<uint32_t>::max(), true},
530 {"0XDeadBeef", 0xdeadbeef, true},
531 {"0x7fffffffffffffff", std::numeric_limits<uint32_t>::max(),
532 false}, // Overflow test.
533 {"-0x8000000000000000", 0, false},
534 {"0x8000000000000000", std::numeric_limits<uint32_t>::max(),
535 false}, // Overflow test.
536 {"-0x8000000000000001", 0, false},
537 {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
538 false}, // Overflow test.
539 {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
540 false}, // Overflow test.
541 {"0x0000000000000000", 0, true},
542 {"0000000000000000", 0, true},
543 {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
544 false}, // Overflow test.
545 {"0x0f", 0x0f, true},
546 {"0f", 0x0f, true},
547 {" 45", 0x45, false},
548 {"\t\n\v\f\r 0x45", 0x45, false},
549 {" 45", 0x45, false},
550 {"45 ", 0x45, false},
551 {"45:", 0x45, false},
552 {"efgh", 0xef, false},
553 {"0xefgh", 0xef, false},
554 {"hgfe", 0, false},
555 {"-", 0, false},
556 {"", 0, false},
557 {"0x", 0, false},
558 };
559
560 for (const auto& i : cases) {
561 uint32_t output = 0;
562 EXPECT_EQ(i.success, HexStringToUInt(i.input, &output));
563 EXPECT_EQ(i.output, output);
564 }
565 // One additional test to verify that conversion of numbers in strings with
566 // embedded NUL characters. The NUL and extra data after it should be
567 // interpreted as junk after the number.
568 const char input[] =
569 "0xc0ffee\0"
570 "9";
571 std::string input_string(input, std::size(input) - 1);
572 uint32_t output;
573 EXPECT_FALSE(HexStringToUInt(input_string, &output));
574 EXPECT_EQ(0xc0ffeeU, output);
575 }
576
TEST(StringNumberConversionsTest,HexStringToInt64)577 TEST(StringNumberConversionsTest, HexStringToInt64) {
578 static const struct {
579 std::string input;
580 int64_t output;
581 bool success;
582 } cases[] = {
583 {"0", 0, true},
584 {"42", 66, true},
585 {"-42", -66, true},
586 {"+42", 66, true},
587 {"40acd88557b", INT64_C(4444444448123), true},
588 {"7fffffff", INT_MAX, true},
589 {"-80000000", INT_MIN, true},
590 {"ffffffff", 0xffffffff, true},
591 {"DeadBeef", 0xdeadbeef, true},
592 {"0x42", 66, true},
593 {"-0x42", -66, true},
594 {"+0x42", 66, true},
595 {"0x40acd88557b", INT64_C(4444444448123), true},
596 {"0x7fffffff", INT_MAX, true},
597 {"-0x80000000", INT_MIN, true},
598 {"0xffffffff", 0xffffffff, true},
599 {"0XDeadBeef", 0xdeadbeef, true},
600 {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
601 {"-0x8000000000000000", std::numeric_limits<int64_t>::min(), true},
602 {"0x8000000000000000", std::numeric_limits<int64_t>::max(),
603 false}, // Overflow test.
604 {"-0x8000000000000001", std::numeric_limits<int64_t>::min(),
605 false}, // Underflow test.
606 {"0x0f", 15, true},
607 {"0f", 15, true},
608 {" 45", 0x45, false},
609 {"\t\n\v\f\r 0x45", 0x45, false},
610 {" 45", 0x45, false},
611 {"45 ", 0x45, false},
612 {"45:", 0x45, false},
613 {"efgh", 0xef, false},
614 {"0xefgh", 0xef, false},
615 {"hgfe", 0, false},
616 {"-", 0, false},
617 {"", 0, false},
618 {"0x", 0, false},
619 };
620
621 for (const auto& i : cases) {
622 int64_t output = 0;
623 EXPECT_EQ(i.success, HexStringToInt64(i.input, &output));
624 EXPECT_EQ(i.output, output);
625 }
626 // One additional test to verify that conversion of numbers in strings with
627 // embedded NUL characters. The NUL and extra data after it should be
628 // interpreted as junk after the number.
629 const char input[] =
630 "0xc0ffee\0"
631 "9";
632 std::string input_string(input, std::size(input) - 1);
633 int64_t output;
634 EXPECT_FALSE(HexStringToInt64(input_string, &output));
635 EXPECT_EQ(0xc0ffee, output);
636 }
637
TEST(StringNumberConversionsTest,HexStringToUInt64)638 TEST(StringNumberConversionsTest, HexStringToUInt64) {
639 static const struct {
640 std::string input;
641 uint64_t output;
642 bool success;
643 } cases[] = {
644 {"0", 0, true},
645 {"42", 66, true},
646 {"-42", 0, false},
647 {"+42", 66, true},
648 {"40acd88557b", INT64_C(4444444448123), true},
649 {"7fffffff", INT_MAX, true},
650 {"-80000000", 0, false},
651 {"ffffffff", 0xffffffff, true},
652 {"DeadBeef", 0xdeadbeef, true},
653 {"0x42", 66, true},
654 {"-0x42", 0, false},
655 {"+0x42", 66, true},
656 {"0x40acd88557b", INT64_C(4444444448123), true},
657 {"0x7fffffff", INT_MAX, true},
658 {"-0x80000000", 0, false},
659 {"0xffffffff", 0xffffffff, true},
660 {"0XDeadBeef", 0xdeadbeef, true},
661 {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
662 {"-0x8000000000000000", 0, false},
663 {"0x8000000000000000", UINT64_C(0x8000000000000000), true},
664 {"-0x8000000000000001", 0, false},
665 {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
666 {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
667 {"0x0000000000000000", 0, true},
668 {"0000000000000000", 0, true},
669 {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(),
670 false}, // Overflow test.
671 {"0x0f", 15, true},
672 {"0f", 15, true},
673 {" 45", 0x45, false},
674 {"\t\n\v\f\r 0x45", 0x45, false},
675 {" 45", 0x45, false},
676 {"45 ", 0x45, false},
677 {"45:", 0x45, false},
678 {"efgh", 0xef, false},
679 {"0xefgh", 0xef, false},
680 {"hgfe", 0, false},
681 {"-", 0, false},
682 {"", 0, false},
683 {"0x", 0, false},
684 };
685
686 for (const auto& i : cases) {
687 uint64_t output = 0;
688 EXPECT_EQ(i.success, HexStringToUInt64(i.input, &output));
689 EXPECT_EQ(i.output, output);
690 }
691 // One additional test to verify that conversion of numbers in strings with
692 // embedded NUL characters. The NUL and extra data after it should be
693 // interpreted as junk after the number.
694 const char input[] =
695 "0xc0ffee\0"
696 "9";
697 std::string input_string(input, std::size(input) - 1);
698 uint64_t output;
699 EXPECT_FALSE(HexStringToUInt64(input_string, &output));
700 EXPECT_EQ(0xc0ffeeU, output);
701 }
702
703 // Tests for HexStringToBytes, HexStringToString, HexStringToSpan.
TEST(StringNumberConversionsTest,HexStringToBytesStringSpan)704 TEST(StringNumberConversionsTest, HexStringToBytesStringSpan) {
705 static const struct {
706 const std::string input;
707 const char* output;
708 size_t output_len;
709 bool success;
710 } cases[] = {
711 {"0", "", 0, false}, // odd number of characters fails
712 {"00", "\0", 1, true},
713 {"42", "\x42", 1, true},
714 {"-42", "", 0, false}, // any non-hex value fails
715 {"+42", "", 0, false},
716 {"7fffffff", "\x7f\xff\xff\xff", 4, true},
717 {"80000000", "\x80\0\0\0", 4, true},
718 {"deadbeef", "\xde\xad\xbe\xef", 4, true},
719 {"DeadBeef", "\xde\xad\xbe\xef", 4, true},
720 {"0x42", "", 0, false}, // leading 0x fails (x is not hex)
721 {"0f", "\xf", 1, true},
722 {"45 ", "\x45", 1, false},
723 {"efgh", "\xef", 1, false},
724 {"", "", 0, false},
725 {"0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8, true},
726 {"0123456789ABCDEF012345", "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45",
727 11, true},
728 };
729
730 for (size_t test_i = 0; test_i < std::size(cases); ++test_i) {
731 const auto& test = cases[test_i];
732
733 std::string expected_output(test.output, test.output_len);
734
735 // Test HexStringToBytes().
736 {
737 std::vector<uint8_t> output;
738 EXPECT_EQ(test.success, HexStringToBytes(test.input, &output))
739 << test_i << ": " << test.input;
740 EXPECT_EQ(expected_output, std::string(output.begin(), output.end()));
741 }
742
743 // Test HexStringToString().
744 {
745 std::string output;
746 EXPECT_EQ(test.success, HexStringToString(test.input, &output))
747 << test_i << ": " << test.input;
748 EXPECT_EQ(expected_output, output) << test_i << ": " << test.input;
749 }
750
751 // Test HexStringToSpan() with a properly sized output.
752 {
753 std::vector<uint8_t> output;
754 output.resize(test.input.size() / 2);
755
756 EXPECT_EQ(test.success, HexStringToSpan(test.input, output))
757 << test_i << ": " << test.input;
758
759 // On failure the output will only have been partially written (with
760 // everything after the failure being 0).
761 for (size_t i = 0; i < test.output_len; ++i) {
762 EXPECT_EQ(test.output[i], static_cast<char>(output[i]))
763 << test_i << ": " << test.input;
764 }
765 for (size_t i = test.output_len; i < output.size(); ++i) {
766 EXPECT_EQ('\0', static_cast<char>(output[i]))
767 << test_i << ": " << test.input;
768 }
769 }
770
771 // Test HexStringToSpan() with an output that is 1 byte too small.
772 {
773 std::vector<uint8_t> output;
774 if (test.input.size() > 1)
775 output.resize(test.input.size() / 2 - 1);
776
777 EXPECT_FALSE(HexStringToSpan(test.input, output))
778 << test_i << ": " << test.input;
779 }
780
781 // Test HexStringToSpan() with an output that is 1 byte too large.
782 {
783 std::vector<uint8_t> output;
784 output.resize(test.input.size() / 2 + 1);
785
786 EXPECT_FALSE(HexStringToSpan(test.input, output))
787 << test_i << ": " << test.input;
788 }
789 }
790 }
791
TEST(StringNumberConversionsTest,StringToDouble)792 TEST(StringNumberConversionsTest, StringToDouble) {
793 static const struct {
794 std::string input;
795 double output;
796 bool success;
797 } cases[] = {
798 // Test different forms of zero.
799 {"0", 0.0, true},
800 {"+0", 0.0, true},
801 {"-0", 0.0, true},
802 {"0.0", 0.0, true},
803 {"000000000000000000000000000000.0", 0.0, true},
804 {"0.000000000000000000000000000", 0.0, true},
805
806 // Test the answer.
807 {"42", 42.0, true},
808 {"-42", -42.0, true},
809
810 // Test variances of an ordinary number.
811 {"123.45", 123.45, true},
812 {"-123.45", -123.45, true},
813 {"+123.45", 123.45, true},
814
815 // Test different forms of representation.
816 {"2.99792458e8", 299792458.0, true},
817 {"149597870.691E+3", 149597870691.0, true},
818 {"6.", 6.0, true},
819
820 // Test around the largest/smallest value that a double can represent.
821 {"9e307", 9e307, true},
822 {"1.7976e308", 1.7976e308, true},
823 {"1.7977e308", HUGE_VAL, false},
824 {"1.797693134862315807e+308", HUGE_VAL, true},
825 {"1.797693134862315808e+308", HUGE_VAL, false},
826 {"9e308", HUGE_VAL, false},
827 {"9e309", HUGE_VAL, false},
828 {"9e999", HUGE_VAL, false},
829 {"9e1999", HUGE_VAL, false},
830 {"9e19999", HUGE_VAL, false},
831 {"9e99999999999999999999", HUGE_VAL, false},
832 {"-9e307", -9e307, true},
833 {"-1.7976e308", -1.7976e308, true},
834 {"-1.7977e308", -HUGE_VAL, false},
835 {"-1.797693134862315807e+308", -HUGE_VAL, true},
836 {"-1.797693134862315808e+308", -HUGE_VAL, false},
837 {"-9e308", -HUGE_VAL, false},
838 {"-9e309", -HUGE_VAL, false},
839 {"-9e999", -HUGE_VAL, false},
840 {"-9e1999", -HUGE_VAL, false},
841 {"-9e19999", -HUGE_VAL, false},
842 {"-9e99999999999999999999", -HUGE_VAL, false},
843
844 // Test more exponents.
845 {"1e-2", 0.01, true},
846 {"42 ", 42.0, false},
847 {" 1e-2", 0.01, false},
848 {"1e-2 ", 0.01, false},
849 {"-1E-7", -0.0000001, true},
850 {"01e02", 100, true},
851 {"2.3e15", 2.3e15, true},
852 {"100e-309", 100e-309, true},
853
854 // Test some invalid cases.
855 {"\t\n\v\f\r -123.45e2", -12345.0, false},
856 {"+123 e4", 123.0, false},
857 {"123e ", 123.0, false},
858 {"123e", 123.0, false},
859 {"10.5px", 10.5, false},
860 {"11.5e2em", 1150, false},
861 {" 2.99", 2.99, false},
862 {"1e3.4", 1000.0, false},
863 {"nothing", 0.0, false},
864 {"-", 0.0, false},
865 {"+", 0.0, false},
866 {"", 0.0, false},
867
868 // crbug.org/588726
869 {"-0.0010000000000000000000000000000000000000001e-256",
870 -1.0000000000000001e-259, true},
871 };
872
873 for (size_t i = 0; i < std::size(cases); ++i) {
874 SCOPED_TRACE(
875 StringPrintf("case %" PRIuS " \"%s\"", i, cases[i].input.c_str()));
876 double output;
877 errno = 1;
878 EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output));
879 if (cases[i].success)
880 EXPECT_EQ(1, errno) << i; // confirm that errno is unchanged.
881 EXPECT_DOUBLE_EQ(cases[i].output, output);
882 }
883
884 // One additional test to verify that conversion of numbers in strings with
885 // embedded NUL characters. The NUL and extra data after it should be
886 // interpreted as junk after the number.
887 const char input[] =
888 "3.14\0"
889 "159";
890 std::string input_string(input, std::size(input) - 1);
891 double output;
892 EXPECT_FALSE(StringToDouble(input_string, &output));
893 EXPECT_DOUBLE_EQ(3.14, output);
894 }
895
TEST(StringNumberConversionsTest,DoubleToString)896 TEST(StringNumberConversionsTest, DoubleToString) {
897 static const struct {
898 double input;
899 const char* expected;
900 } cases[] = {
901 {0.0, "0"},
902 {0.5, "0.5"},
903 {1.25, "1.25"},
904 {1.33518e+012, "1.33518e+12"},
905 {1.33489e+012, "1.33489e+12"},
906 {1.33505e+012, "1.33505e+12"},
907 {1.33545e+009, "1335450000"},
908 {1.33503e+009, "1335030000"},
909 };
910
911 for (const auto& i : cases) {
912 EXPECT_EQ(i.expected, NumberToString(i.input));
913 EXPECT_EQ(i.expected, UTF16ToUTF8(NumberToString16(i.input)));
914 }
915
916 // The following two values were seen in crashes in the wild.
917 const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'};
918 double input = 0;
919 memcpy(&input, input_bytes, std::size(input_bytes));
920 EXPECT_EQ("1.335179083776e+12", NumberToString(input));
921 const char input_bytes2[8] = {0, 0, 0, '\xa0',
922 '\xda', '\x6c', '\x73', '\x42'};
923 input = 0;
924 memcpy(&input, input_bytes2, std::size(input_bytes2));
925 EXPECT_EQ("1.33489033216e+12", NumberToString(input));
926 }
927
TEST(StringNumberConversionsTest,AppendHexEncodedByte)928 TEST(StringNumberConversionsTest, AppendHexEncodedByte) {
929 std::string hex;
930 AppendHexEncodedByte(0, hex);
931 AppendHexEncodedByte(0, hex, false);
932 AppendHexEncodedByte(1, hex);
933 AppendHexEncodedByte(1, hex, false);
934 AppendHexEncodedByte(0xf, hex);
935 AppendHexEncodedByte(0xf, hex, false);
936 AppendHexEncodedByte(0x8a, hex);
937 AppendHexEncodedByte(0x8a, hex, false);
938 AppendHexEncodedByte(0xe0, hex);
939 AppendHexEncodedByte(0xe0, hex, false);
940 AppendHexEncodedByte(0xff, hex);
941 AppendHexEncodedByte(0xff, hex, false);
942 EXPECT_EQ(hex, "000001010F0f8A8aE0e0FFff");
943 }
944
TEST(StringNumberConversionsTest,HexEncode)945 TEST(StringNumberConversionsTest, HexEncode) {
946 EXPECT_EQ(HexEncode(nullptr, 0), "");
947 EXPECT_EQ(HexEncode(base::span<uint8_t>()), "");
948 EXPECT_EQ(HexEncode(std::string()), "");
949
950 const uint8_t kBytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81};
951 EXPECT_EQ(HexEncode(kBytes, sizeof(kBytes)), "01FF02FE038081");
952 EXPECT_EQ(HexEncode(kBytes), "01FF02FE038081"); // Implicit span conversion.
953
954 const std::string kString = "\x01\xff";
955 EXPECT_EQ(HexEncode(kString.c_str(), kString.size()), "01FF");
956 EXPECT_EQ(HexEncode(kString),
957 "01FF"); // Implicit std::string_view conversion.
958 }
959
960 // Test cases of known-bad strtod conversions that motivated the use of dmg_fp.
961 // See https://bugs.chromium.org/p/chromium/issues/detail?id=593512.
TEST(StringNumberConversionsTest,StrtodFailures)962 TEST(StringNumberConversionsTest, StrtodFailures) {
963 static const struct {
964 const char* input;
965 uint64_t expected;
966 } cases[] = {
967 // http://www.exploringbinary.com/incorrectly-rounded-conversions-in-visual-c-plus-plus/
968 {"9214843084008499", 0x43405e6cec57761aULL},
969 {"0.500000000000000166533453693773481063544750213623046875",
970 0x3fe0000000000002ULL},
971 {"30078505129381147446200", 0x44997a3c7271b021ULL},
972 {"1777820000000000000001", 0x4458180d5bad2e3eULL},
973 {"0.500000000000000166547006220929549868969843373633921146392822265625",
974 0x3fe0000000000002ULL},
975 {"0.50000000000000016656055874808561867439493653364479541778564453125",
976 0x3fe0000000000002ULL},
977 {"0.3932922657273", 0x3fd92bb352c4623aULL},
978
979 // http://www.exploringbinary.com/incorrectly-rounded-conversions-in-gcc-and-glibc/
980 {"0.500000000000000166533453693773481063544750213623046875",
981 0x3fe0000000000002ULL},
982 {"3.518437208883201171875e13", 0x42c0000000000002ULL},
983 {"62.5364939768271845828", 0x404f44abd5aa7ca4ULL},
984 {"8.10109172351e-10", 0x3e0bd5cbaef0fd0cULL},
985 {"1.50000000000000011102230246251565404236316680908203125",
986 0x3ff8000000000000ULL},
987 {"9007199254740991.4999999999999999999999999999999995",
988 0x433fffffffffffffULL},
989
990 // http://www.exploringbinary.com/incorrect-decimal-to-floating-point-conversion-in-sqlite/
991 {"1e-23", 0x3b282db34012b251ULL},
992 {"8.533e+68", 0x4e3fa69165a8eea2ULL},
993 {"4.1006e-184", 0x19dbe0d1c7ea60c9ULL},
994 {"9.998e+307", 0x7fe1cc0a350ca87bULL},
995 {"9.9538452227e-280", 0x0602117ae45cde43ULL},
996 {"6.47660115e-260", 0x0a1fdd9e333badadULL},
997 {"7.4e+47", 0x49e033d7eca0adefULL},
998 {"5.92e+48", 0x4a1033d7eca0adefULL},
999 {"7.35e+66", 0x4dd172b70eababa9ULL},
1000 {"8.32116e+55", 0x4b8b2628393e02cdULL},
1001 };
1002
1003 for (const auto& test : cases) {
1004 SCOPED_TRACE(StringPrintf("input: \"%s\"", test.input));
1005 double output;
1006 EXPECT_TRUE(StringToDouble(test.input, &output));
1007 EXPECT_EQ(bit_cast<uint64_t>(output), test.expected);
1008 }
1009 }
1010
1011 } // namespace base
1012