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