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