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