15
15
#include " src/libfuzzer/libfuzzer_macro.h"
16
16
17
17
#include < algorithm>
18
+ #include < memory>
19
+ #include < vector>
18
20
19
21
#include " src/binary_format.h"
20
22
#include " src/libfuzzer/libfuzzer_mutator.h"
@@ -91,6 +93,35 @@ class BinaryOutputWriter : public OutputWriter {
91
93
}
92
94
};
93
95
96
+ class LastMutationCache {
97
+ public:
98
+ void Store (const uint8_t * data, size_t size, protobuf::Message* message) {
99
+ if (!message_) message_.reset (message->New ());
100
+ message->GetReflection ()->Swap (message, message_.get ());
101
+ data_.assign (data, data + size);
102
+ }
103
+
104
+ bool LoadIfSame (const uint8_t * data, size_t size,
105
+ protobuf::Message* message) {
106
+ if (!message_ || size != data_.size () ||
107
+ !std::equal (data_.begin (), data_.end (), data))
108
+ return false ;
109
+
110
+ message->GetReflection ()->Swap (message, message_.get ());
111
+ message_.reset ();
112
+ return true ;
113
+ }
114
+
115
+ private:
116
+ std::vector<uint8_t > data_;
117
+ std::unique_ptr<protobuf::Message> message_;
118
+ };
119
+
120
+ LastMutationCache* GetCache () {
121
+ static LastMutationCache cache;
122
+ return &cache;
123
+ }
124
+
94
125
Mutator* GetMutator () {
95
126
static Mutator mutator;
96
127
return &mutator;
@@ -111,6 +142,7 @@ size_t MutateMessage(unsigned int seed, const InputReader& input,
111
142
GetMutator ()->Mutate (message, max_size);
112
143
if (size_t new_size = output->Write (*message)) {
113
144
assert (new_size <= output->size ());
145
+ GetCache ()->Store (output->data (), new_size, message);
114
146
return new_size;
115
147
}
116
148
return 0 ;
@@ -127,6 +159,7 @@ size_t CrossOverMessages(unsigned int seed, const InputReader& input1,
127
159
GetMutator ()->CrossOver (*message2, message1, max_size);
128
160
if (size_t new_size = output->Write (*message1)) {
129
161
assert (new_size <= output->size ());
162
+ GetCache ()->Store (output->data (), new_size, message1);
130
163
return new_size;
131
164
}
132
165
return 0 ;
@@ -189,6 +222,7 @@ size_t CustomProtoCrossOver(bool binary, const uint8_t* data1, size_t size1,
189
222
190
223
bool LoadProtoInput (bool binary, const uint8_t * data, size_t size,
191
224
protobuf::Message* input) {
225
+ if (GetCache ()->LoadIfSame (data, size, input)) return true ;
192
226
auto result = binary ? ParseBinaryMessage (data, size, input)
193
227
: ParseTextMessage (data, size, input);
194
228
if (!result) return false ;
0 commit comments