1 // Copyright 2015 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 <stddef.h>
8 #include <stdint.h>
9
10 #include <string>
11 #include <string_view>
12 #include <vector>
13
14 template <class NumberType, class StringPieceType, class StringType>
CheckRoundtripsT(const uint8_t * data,const size_t size,StringType (* num_to_string)(NumberType),bool (* string_to_num)(StringPieceType,NumberType *))15 void CheckRoundtripsT(const uint8_t* data,
16 const size_t size,
17 StringType (*num_to_string)(NumberType),
18 bool (*string_to_num)(StringPieceType, NumberType*)) {
19 // Ensure we can read a NumberType from |data|
20 if (size < sizeof(NumberType))
21 return;
22 const NumberType v1 = *reinterpret_cast<const NumberType*>(data);
23
24 // Because we started with an arbitrary NumberType value, not an arbitrary
25 // string, we expect that the function |string_to_num| (e.g. StringToInt) will
26 // return true, indicating a perfect conversion.
27 NumberType v2;
28 CHECK(string_to_num(num_to_string(v1), &v2));
29
30 // Given that this was a perfect conversion, we expect the original NumberType
31 // value to equal the newly parsed one.
32 CHECK_EQ(v1, v2);
33 }
34
35 template <class NumberType>
CheckRoundtrips(const uint8_t * data,const size_t size,bool (* string_to_num)(std::string_view,NumberType *))36 void CheckRoundtrips(const uint8_t* data,
37 const size_t size,
38 bool (*string_to_num)(std::string_view, NumberType*)) {
39 return CheckRoundtripsT<NumberType, std::string_view, std::string>(
40 data, size, &base::NumberToString, string_to_num);
41 }
42
43 template <class NumberType>
CheckRoundtrips16(const uint8_t * data,const size_t size,bool (* string_to_num)(std::u16string_view,NumberType *))44 void CheckRoundtrips16(const uint8_t* data,
45 const size_t size,
46 bool (*string_to_num)(std::u16string_view,
47 NumberType*)) {
48 return CheckRoundtripsT<NumberType, std::u16string_view, std::u16string>(
49 data, size, &base::NumberToString16, string_to_num);
50 }
51
52 // Entry point for LibFuzzer.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)53 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
54 // For each instantiation of NumberToString f and its corresponding StringTo*
55 // function g, check that f(g(x)) = x holds for fuzzer-determined values of x.
56 CheckRoundtrips<int>(data, size, &base::StringToInt);
57 CheckRoundtrips16<int>(data, size, &base::StringToInt);
58 CheckRoundtrips<unsigned int>(data, size, &base::StringToUint);
59 CheckRoundtrips16<unsigned int>(data, size, &base::StringToUint);
60 CheckRoundtrips<int64_t>(data, size, &base::StringToInt64);
61 CheckRoundtrips16<int64_t>(data, size, &base::StringToInt64);
62 CheckRoundtrips<uint64_t>(data, size, &base::StringToUint64);
63 CheckRoundtrips16<uint64_t>(data, size, &base::StringToUint64);
64 CheckRoundtrips<size_t>(data, size, &base::StringToSizeT);
65 CheckRoundtrips16<size_t>(data, size, &base::StringToSizeT);
66
67 std::string_view string_piece_input(reinterpret_cast<const char*>(data),
68 size);
69 std::string string_input(reinterpret_cast<const char*>(data), size);
70
71 int out_int;
72 base::StringToInt(string_piece_input, &out_int);
73 unsigned out_uint;
74 base::StringToUint(string_piece_input, &out_uint);
75 int64_t out_int64;
76 base::StringToInt64(string_piece_input, &out_int64);
77 uint64_t out_uint64;
78 base::StringToUint64(string_piece_input, &out_uint64);
79 size_t out_size;
80 base::StringToSizeT(string_piece_input, &out_size);
81
82 // Test for std::u16string_view if size is even.
83 if (size % 2 == 0) {
84 std::u16string_view string_piece_input16(
85 reinterpret_cast<const char16_t*>(data), size / 2);
86
87 base::StringToInt(string_piece_input16, &out_int);
88 base::StringToUint(string_piece_input16, &out_uint);
89 base::StringToInt64(string_piece_input16, &out_int64);
90 base::StringToUint64(string_piece_input16, &out_uint64);
91 base::StringToSizeT(string_piece_input16, &out_size);
92 }
93
94 double out_double;
95 base::StringToDouble(string_input, &out_double);
96
97 base::HexStringToInt(string_piece_input, &out_int);
98 base::HexStringToUInt(string_piece_input, &out_uint);
99 base::HexStringToInt64(string_piece_input, &out_int64);
100 base::HexStringToUInt64(string_piece_input, &out_uint64);
101 std::vector<uint8_t> out_bytes;
102 base::HexStringToBytes(string_piece_input, &out_bytes);
103
104 base::HexEncode(data, size);
105
106 // Convert the numbers back to strings.
107 base::NumberToString(out_int);
108 base::NumberToString16(out_int);
109 base::NumberToString(out_uint);
110 base::NumberToString16(out_uint);
111 base::NumberToString(out_int64);
112 base::NumberToString16(out_int64);
113 base::NumberToString(out_uint64);
114 base::NumberToString16(out_uint64);
115 base::NumberToString(out_double);
116 base::NumberToString16(out_double);
117
118 return 0;
119 }
120