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