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