xref: /aosp_15_r20/external/libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.cc (revision fd525a9c096e28cf6f8d8719388df0568a611e7b)
1*fd525a9cSAndroid Build Coastguard Worker // Copyright 2017 Google Inc. All rights reserved.
2*fd525a9cSAndroid Build Coastguard Worker //
3*fd525a9cSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*fd525a9cSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*fd525a9cSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*fd525a9cSAndroid Build Coastguard Worker //
7*fd525a9cSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*fd525a9cSAndroid Build Coastguard Worker //
9*fd525a9cSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*fd525a9cSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*fd525a9cSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*fd525a9cSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*fd525a9cSAndroid Build Coastguard Worker // limitations under the License.
14*fd525a9cSAndroid Build Coastguard Worker 
15*fd525a9cSAndroid Build Coastguard Worker #include "src/libfuzzer/libfuzzer_macro.h"
16*fd525a9cSAndroid Build Coastguard Worker 
17*fd525a9cSAndroid Build Coastguard Worker #include <algorithm>
18*fd525a9cSAndroid Build Coastguard Worker #include <memory>
19*fd525a9cSAndroid Build Coastguard Worker #include <vector>
20*fd525a9cSAndroid Build Coastguard Worker 
21*fd525a9cSAndroid Build Coastguard Worker #include "src/binary_format.h"
22*fd525a9cSAndroid Build Coastguard Worker #include "src/libfuzzer/libfuzzer_mutator.h"
23*fd525a9cSAndroid Build Coastguard Worker #include "src/text_format.h"
24*fd525a9cSAndroid Build Coastguard Worker 
25*fd525a9cSAndroid Build Coastguard Worker namespace protobuf_mutator {
26*fd525a9cSAndroid Build Coastguard Worker namespace libfuzzer {
27*fd525a9cSAndroid Build Coastguard Worker 
28*fd525a9cSAndroid Build Coastguard Worker namespace {
29*fd525a9cSAndroid Build Coastguard Worker 
30*fd525a9cSAndroid Build Coastguard Worker class InputReader {
31*fd525a9cSAndroid Build Coastguard Worker  public:
InputReader(const uint8_t * data,size_t size)32*fd525a9cSAndroid Build Coastguard Worker   InputReader(const uint8_t* data, size_t size) : data_(data), size_(size) {}
33*fd525a9cSAndroid Build Coastguard Worker   virtual ~InputReader() = default;
34*fd525a9cSAndroid Build Coastguard Worker 
35*fd525a9cSAndroid Build Coastguard Worker   virtual bool Read(protobuf::Message* message) const = 0;
36*fd525a9cSAndroid Build Coastguard Worker 
data() const37*fd525a9cSAndroid Build Coastguard Worker   const uint8_t* data() const { return data_; }
size() const38*fd525a9cSAndroid Build Coastguard Worker   size_t size() const { return size_; }
39*fd525a9cSAndroid Build Coastguard Worker 
40*fd525a9cSAndroid Build Coastguard Worker  private:
41*fd525a9cSAndroid Build Coastguard Worker   const uint8_t* data_;
42*fd525a9cSAndroid Build Coastguard Worker   size_t size_;
43*fd525a9cSAndroid Build Coastguard Worker };
44*fd525a9cSAndroid Build Coastguard Worker 
45*fd525a9cSAndroid Build Coastguard Worker class OutputWriter {
46*fd525a9cSAndroid Build Coastguard Worker  public:
OutputWriter(uint8_t * data,size_t size)47*fd525a9cSAndroid Build Coastguard Worker   OutputWriter(uint8_t* data, size_t size) : data_(data), size_(size) {}
48*fd525a9cSAndroid Build Coastguard Worker   virtual ~OutputWriter() = default;
49*fd525a9cSAndroid Build Coastguard Worker 
50*fd525a9cSAndroid Build Coastguard Worker   virtual size_t Write(const protobuf::Message& message) = 0;
51*fd525a9cSAndroid Build Coastguard Worker 
data() const52*fd525a9cSAndroid Build Coastguard Worker   uint8_t* data() const { return data_; }
size() const53*fd525a9cSAndroid Build Coastguard Worker   size_t size() const { return size_; }
54*fd525a9cSAndroid Build Coastguard Worker 
55*fd525a9cSAndroid Build Coastguard Worker  private:
56*fd525a9cSAndroid Build Coastguard Worker   uint8_t* data_;
57*fd525a9cSAndroid Build Coastguard Worker   size_t size_;
58*fd525a9cSAndroid Build Coastguard Worker };
59*fd525a9cSAndroid Build Coastguard Worker 
60*fd525a9cSAndroid Build Coastguard Worker class TextInputReader : public InputReader {
61*fd525a9cSAndroid Build Coastguard Worker  public:
62*fd525a9cSAndroid Build Coastguard Worker   using InputReader::InputReader;
63*fd525a9cSAndroid Build Coastguard Worker 
Read(protobuf::Message * message) const64*fd525a9cSAndroid Build Coastguard Worker   bool Read(protobuf::Message* message) const override {
65*fd525a9cSAndroid Build Coastguard Worker     return ParseTextMessage(data(), size(), message);
66*fd525a9cSAndroid Build Coastguard Worker   }
67*fd525a9cSAndroid Build Coastguard Worker };
68*fd525a9cSAndroid Build Coastguard Worker 
69*fd525a9cSAndroid Build Coastguard Worker class TextOutputWriter : public OutputWriter {
70*fd525a9cSAndroid Build Coastguard Worker  public:
71*fd525a9cSAndroid Build Coastguard Worker   using OutputWriter::OutputWriter;
72*fd525a9cSAndroid Build Coastguard Worker 
Write(const protobuf::Message & message)73*fd525a9cSAndroid Build Coastguard Worker   size_t Write(const protobuf::Message& message) override {
74*fd525a9cSAndroid Build Coastguard Worker     return SaveMessageAsText(message, data(), size());
75*fd525a9cSAndroid Build Coastguard Worker   }
76*fd525a9cSAndroid Build Coastguard Worker };
77*fd525a9cSAndroid Build Coastguard Worker 
78*fd525a9cSAndroid Build Coastguard Worker class BinaryInputReader : public InputReader {
79*fd525a9cSAndroid Build Coastguard Worker  public:
80*fd525a9cSAndroid Build Coastguard Worker   using InputReader::InputReader;
81*fd525a9cSAndroid Build Coastguard Worker 
Read(protobuf::Message * message) const82*fd525a9cSAndroid Build Coastguard Worker   bool Read(protobuf::Message* message) const override {
83*fd525a9cSAndroid Build Coastguard Worker     return ParseBinaryMessage(data(), size(), message);
84*fd525a9cSAndroid Build Coastguard Worker   }
85*fd525a9cSAndroid Build Coastguard Worker };
86*fd525a9cSAndroid Build Coastguard Worker 
87*fd525a9cSAndroid Build Coastguard Worker class BinaryOutputWriter : public OutputWriter {
88*fd525a9cSAndroid Build Coastguard Worker  public:
89*fd525a9cSAndroid Build Coastguard Worker   using OutputWriter::OutputWriter;
90*fd525a9cSAndroid Build Coastguard Worker 
Write(const protobuf::Message & message)91*fd525a9cSAndroid Build Coastguard Worker   size_t Write(const protobuf::Message& message) override {
92*fd525a9cSAndroid Build Coastguard Worker     return SaveMessageAsBinary(message, data(), size());
93*fd525a9cSAndroid Build Coastguard Worker   }
94*fd525a9cSAndroid Build Coastguard Worker };
95*fd525a9cSAndroid Build Coastguard Worker 
96*fd525a9cSAndroid Build Coastguard Worker class LastMutationCache {
97*fd525a9cSAndroid Build Coastguard Worker  public:
Store(const uint8_t * data,size_t size,protobuf::Message * message)98*fd525a9cSAndroid Build Coastguard Worker   void Store(const uint8_t* data, size_t size, protobuf::Message* message) {
99*fd525a9cSAndroid Build Coastguard Worker     if (!message_) message_.reset(message->New());
100*fd525a9cSAndroid Build Coastguard Worker     message->GetReflection()->Swap(message, message_.get());
101*fd525a9cSAndroid Build Coastguard Worker     data_.assign(data, data + size);
102*fd525a9cSAndroid Build Coastguard Worker   }
103*fd525a9cSAndroid Build Coastguard Worker 
LoadIfSame(const uint8_t * data,size_t size,protobuf::Message * message)104*fd525a9cSAndroid Build Coastguard Worker   bool LoadIfSame(const uint8_t* data, size_t size,
105*fd525a9cSAndroid Build Coastguard Worker                   protobuf::Message* message) {
106*fd525a9cSAndroid Build Coastguard Worker     if (!message_ || size != data_.size() ||
107*fd525a9cSAndroid Build Coastguard Worker         !std::equal(data_.begin(), data_.end(), data))
108*fd525a9cSAndroid Build Coastguard Worker       return false;
109*fd525a9cSAndroid Build Coastguard Worker 
110*fd525a9cSAndroid Build Coastguard Worker     message->GetReflection()->Swap(message, message_.get());
111*fd525a9cSAndroid Build Coastguard Worker     message_.reset();
112*fd525a9cSAndroid Build Coastguard Worker     return true;
113*fd525a9cSAndroid Build Coastguard Worker   }
114*fd525a9cSAndroid Build Coastguard Worker 
115*fd525a9cSAndroid Build Coastguard Worker  private:
116*fd525a9cSAndroid Build Coastguard Worker   std::vector<uint8_t> data_;
117*fd525a9cSAndroid Build Coastguard Worker   std::unique_ptr<protobuf::Message> message_;
118*fd525a9cSAndroid Build Coastguard Worker };
119*fd525a9cSAndroid Build Coastguard Worker 
GetCache()120*fd525a9cSAndroid Build Coastguard Worker LastMutationCache* GetCache() {
121*fd525a9cSAndroid Build Coastguard Worker   static LastMutationCache cache;
122*fd525a9cSAndroid Build Coastguard Worker   return &cache;
123*fd525a9cSAndroid Build Coastguard Worker }
124*fd525a9cSAndroid Build Coastguard Worker 
GetMutator()125*fd525a9cSAndroid Build Coastguard Worker Mutator* GetMutator() {
126*fd525a9cSAndroid Build Coastguard Worker   static Mutator mutator;
127*fd525a9cSAndroid Build Coastguard Worker   return &mutator;
128*fd525a9cSAndroid Build Coastguard Worker }
129*fd525a9cSAndroid Build Coastguard Worker 
GetMaxSize(const InputReader & input,const OutputWriter & output,const protobuf::Message & message)130*fd525a9cSAndroid Build Coastguard Worker size_t GetMaxSize(const InputReader& input, const OutputWriter& output,
131*fd525a9cSAndroid Build Coastguard Worker                   const protobuf::Message& message) {
132*fd525a9cSAndroid Build Coastguard Worker   size_t max_size = message.ByteSizeLong() + output.size();
133*fd525a9cSAndroid Build Coastguard Worker   max_size -= std::min(max_size, input.size());
134*fd525a9cSAndroid Build Coastguard Worker   return max_size;
135*fd525a9cSAndroid Build Coastguard Worker }
136*fd525a9cSAndroid Build Coastguard Worker 
MutateMessage(unsigned int seed,const InputReader & input,OutputWriter * output,protobuf::Message * message)137*fd525a9cSAndroid Build Coastguard Worker size_t MutateMessage(unsigned int seed, const InputReader& input,
138*fd525a9cSAndroid Build Coastguard Worker                      OutputWriter* output, protobuf::Message* message) {
139*fd525a9cSAndroid Build Coastguard Worker   GetMutator()->Seed(seed);
140*fd525a9cSAndroid Build Coastguard Worker   input.Read(message);
141*fd525a9cSAndroid Build Coastguard Worker   size_t max_size = GetMaxSize(input, *output, *message);
142*fd525a9cSAndroid Build Coastguard Worker   GetMutator()->Mutate(message, max_size);
143*fd525a9cSAndroid Build Coastguard Worker   if (size_t new_size = output->Write(*message)) {
144*fd525a9cSAndroid Build Coastguard Worker     assert(new_size <= output->size());
145*fd525a9cSAndroid Build Coastguard Worker     GetCache()->Store(output->data(), new_size, message);
146*fd525a9cSAndroid Build Coastguard Worker     return new_size;
147*fd525a9cSAndroid Build Coastguard Worker   }
148*fd525a9cSAndroid Build Coastguard Worker   return 0;
149*fd525a9cSAndroid Build Coastguard Worker }
150*fd525a9cSAndroid Build Coastguard Worker 
CrossOverMessages(unsigned int seed,const InputReader & input1,const InputReader & input2,OutputWriter * output,protobuf::Message * message1,protobuf::Message * message2)151*fd525a9cSAndroid Build Coastguard Worker size_t CrossOverMessages(unsigned int seed, const InputReader& input1,
152*fd525a9cSAndroid Build Coastguard Worker                          const InputReader& input2, OutputWriter* output,
153*fd525a9cSAndroid Build Coastguard Worker                          protobuf::Message* message1,
154*fd525a9cSAndroid Build Coastguard Worker                          protobuf::Message* message2) {
155*fd525a9cSAndroid Build Coastguard Worker   GetMutator()->Seed(seed);
156*fd525a9cSAndroid Build Coastguard Worker   input1.Read(message1);
157*fd525a9cSAndroid Build Coastguard Worker   input2.Read(message2);
158*fd525a9cSAndroid Build Coastguard Worker   size_t max_size = GetMaxSize(input1, *output, *message1);
159*fd525a9cSAndroid Build Coastguard Worker   GetMutator()->CrossOver(*message2, message1, max_size);
160*fd525a9cSAndroid Build Coastguard Worker   if (size_t new_size = output->Write(*message1)) {
161*fd525a9cSAndroid Build Coastguard Worker     assert(new_size <= output->size());
162*fd525a9cSAndroid Build Coastguard Worker     GetCache()->Store(output->data(), new_size, message1);
163*fd525a9cSAndroid Build Coastguard Worker     return new_size;
164*fd525a9cSAndroid Build Coastguard Worker   }
165*fd525a9cSAndroid Build Coastguard Worker   return 0;
166*fd525a9cSAndroid Build Coastguard Worker }
167*fd525a9cSAndroid Build Coastguard Worker 
MutateTextMessage(uint8_t * data,size_t size,size_t max_size,unsigned int seed,protobuf::Message * message)168*fd525a9cSAndroid Build Coastguard Worker size_t MutateTextMessage(uint8_t* data, size_t size, size_t max_size,
169*fd525a9cSAndroid Build Coastguard Worker                          unsigned int seed, protobuf::Message* message) {
170*fd525a9cSAndroid Build Coastguard Worker   TextInputReader input(data, size);
171*fd525a9cSAndroid Build Coastguard Worker   TextOutputWriter output(data, max_size);
172*fd525a9cSAndroid Build Coastguard Worker   return MutateMessage(seed, input, &output, message);
173*fd525a9cSAndroid Build Coastguard Worker }
174*fd525a9cSAndroid Build Coastguard Worker 
CrossOverTextMessages(const uint8_t * data1,size_t size1,const uint8_t * data2,size_t size2,uint8_t * out,size_t max_out_size,unsigned int seed,protobuf::Message * message1,protobuf::Message * message2)175*fd525a9cSAndroid Build Coastguard Worker size_t CrossOverTextMessages(const uint8_t* data1, size_t size1,
176*fd525a9cSAndroid Build Coastguard Worker                              const uint8_t* data2, size_t size2, uint8_t* out,
177*fd525a9cSAndroid Build Coastguard Worker                              size_t max_out_size, unsigned int seed,
178*fd525a9cSAndroid Build Coastguard Worker                              protobuf::Message* message1,
179*fd525a9cSAndroid Build Coastguard Worker                              protobuf::Message* message2) {
180*fd525a9cSAndroid Build Coastguard Worker   TextInputReader input1(data1, size1);
181*fd525a9cSAndroid Build Coastguard Worker   TextInputReader input2(data2, size2);
182*fd525a9cSAndroid Build Coastguard Worker   TextOutputWriter output(out, max_out_size);
183*fd525a9cSAndroid Build Coastguard Worker   return CrossOverMessages(seed, input1, input2, &output, message1, message2);
184*fd525a9cSAndroid Build Coastguard Worker }
185*fd525a9cSAndroid Build Coastguard Worker 
MutateBinaryMessage(uint8_t * data,size_t size,size_t max_size,unsigned int seed,protobuf::Message * message)186*fd525a9cSAndroid Build Coastguard Worker size_t MutateBinaryMessage(uint8_t* data, size_t size, size_t max_size,
187*fd525a9cSAndroid Build Coastguard Worker                            unsigned int seed, protobuf::Message* message) {
188*fd525a9cSAndroid Build Coastguard Worker   BinaryInputReader input(data, size);
189*fd525a9cSAndroid Build Coastguard Worker   BinaryOutputWriter output(data, max_size);
190*fd525a9cSAndroid Build Coastguard Worker   return MutateMessage(seed, input, &output, message);
191*fd525a9cSAndroid Build Coastguard Worker }
192*fd525a9cSAndroid Build Coastguard Worker 
CrossOverBinaryMessages(const uint8_t * data1,size_t size1,const uint8_t * data2,size_t size2,uint8_t * out,size_t max_out_size,unsigned int seed,protobuf::Message * message1,protobuf::Message * message2)193*fd525a9cSAndroid Build Coastguard Worker size_t CrossOverBinaryMessages(const uint8_t* data1, size_t size1,
194*fd525a9cSAndroid Build Coastguard Worker                                const uint8_t* data2, size_t size2, uint8_t* out,
195*fd525a9cSAndroid Build Coastguard Worker                                size_t max_out_size, unsigned int seed,
196*fd525a9cSAndroid Build Coastguard Worker                                protobuf::Message* message1,
197*fd525a9cSAndroid Build Coastguard Worker                                protobuf::Message* message2) {
198*fd525a9cSAndroid Build Coastguard Worker   BinaryInputReader input1(data1, size1);
199*fd525a9cSAndroid Build Coastguard Worker   BinaryInputReader input2(data2, size2);
200*fd525a9cSAndroid Build Coastguard Worker   BinaryOutputWriter output(out, max_out_size);
201*fd525a9cSAndroid Build Coastguard Worker   return CrossOverMessages(seed, input1, input2, &output, message1, message2);
202*fd525a9cSAndroid Build Coastguard Worker }
203*fd525a9cSAndroid Build Coastguard Worker 
204*fd525a9cSAndroid Build Coastguard Worker }  // namespace
205*fd525a9cSAndroid Build Coastguard Worker 
CustomProtoMutator(bool binary,uint8_t * data,size_t size,size_t max_size,unsigned int seed,protobuf::Message * input)206*fd525a9cSAndroid Build Coastguard Worker size_t CustomProtoMutator(bool binary, uint8_t* data, size_t size,
207*fd525a9cSAndroid Build Coastguard Worker                           size_t max_size, unsigned int seed,
208*fd525a9cSAndroid Build Coastguard Worker                           protobuf::Message* input) {
209*fd525a9cSAndroid Build Coastguard Worker   auto mutate = binary ? &MutateBinaryMessage : &MutateTextMessage;
210*fd525a9cSAndroid Build Coastguard Worker   return mutate(data, size, max_size, seed, input);
211*fd525a9cSAndroid Build Coastguard Worker }
212*fd525a9cSAndroid Build Coastguard Worker 
CustomProtoCrossOver(bool binary,const uint8_t * data1,size_t size1,const uint8_t * data2,size_t size2,uint8_t * out,size_t max_out_size,unsigned int seed,protobuf::Message * input1,protobuf::Message * input2)213*fd525a9cSAndroid Build Coastguard Worker size_t CustomProtoCrossOver(bool binary, const uint8_t* data1, size_t size1,
214*fd525a9cSAndroid Build Coastguard Worker                             const uint8_t* data2, size_t size2, uint8_t* out,
215*fd525a9cSAndroid Build Coastguard Worker                             size_t max_out_size, unsigned int seed,
216*fd525a9cSAndroid Build Coastguard Worker                             protobuf::Message* input1,
217*fd525a9cSAndroid Build Coastguard Worker                             protobuf::Message* input2) {
218*fd525a9cSAndroid Build Coastguard Worker   auto cross = binary ? &CrossOverBinaryMessages : &CrossOverTextMessages;
219*fd525a9cSAndroid Build Coastguard Worker   return cross(data1, size1, data2, size2, out, max_out_size, seed, input1,
220*fd525a9cSAndroid Build Coastguard Worker                input2);
221*fd525a9cSAndroid Build Coastguard Worker }
222*fd525a9cSAndroid Build Coastguard Worker 
LoadProtoInput(bool binary,const uint8_t * data,size_t size,protobuf::Message * input)223*fd525a9cSAndroid Build Coastguard Worker bool LoadProtoInput(bool binary, const uint8_t* data, size_t size,
224*fd525a9cSAndroid Build Coastguard Worker                     protobuf::Message* input) {
225*fd525a9cSAndroid Build Coastguard Worker   if (GetCache()->LoadIfSame(data, size, input)) return true;
226*fd525a9cSAndroid Build Coastguard Worker   auto result = binary ? ParseBinaryMessage(data, size, input)
227*fd525a9cSAndroid Build Coastguard Worker                        : ParseTextMessage(data, size, input);
228*fd525a9cSAndroid Build Coastguard Worker   if (!result) return false;
229*fd525a9cSAndroid Build Coastguard Worker   GetMutator()->Seed(size);
230*fd525a9cSAndroid Build Coastguard Worker   GetMutator()->Fix(input);
231*fd525a9cSAndroid Build Coastguard Worker   return true;
232*fd525a9cSAndroid Build Coastguard Worker }
233*fd525a9cSAndroid Build Coastguard Worker 
RegisterPostProcessor(const protobuf::Descriptor * desc,std::function<void (protobuf::Message * message,unsigned int seed)> callback)234*fd525a9cSAndroid Build Coastguard Worker void RegisterPostProcessor(
235*fd525a9cSAndroid Build Coastguard Worker     const protobuf::Descriptor* desc,
236*fd525a9cSAndroid Build Coastguard Worker     std::function<void(protobuf::Message* message, unsigned int seed)>
237*fd525a9cSAndroid Build Coastguard Worker         callback) {
238*fd525a9cSAndroid Build Coastguard Worker   GetMutator()->RegisterPostProcessor(desc, callback);
239*fd525a9cSAndroid Build Coastguard Worker }
240*fd525a9cSAndroid Build Coastguard Worker 
241*fd525a9cSAndroid Build Coastguard Worker }  // namespace libfuzzer
242*fd525a9cSAndroid Build Coastguard Worker }  // namespace protobuf_mutator
243