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