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