• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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