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