blob: ac936cf9055a3bf3e2562dda2e39e418425a17a6 [file] [log] [blame]
Vitaly Buka00b61072016-10-19 23:22:511// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Vitaly Bukaf90698f2017-03-01 23:46:5815#include "src/mutator.h"
Vitaly Buka00b61072016-10-19 23:22:5116
Vitaly Buka781853c2016-11-22 07:09:3517#include <algorithm>
Vitaly Buka0e17fd72016-11-18 18:02:4618#include <map>
Vitaly Buka781853c2016-11-22 07:09:3519#include <random>
Vitaly Buka0e17fd72016-11-18 18:02:4620#include <string>
Allen-Webbc4fa5912018-09-07 22:53:3021#include <vector>
Vitaly Buka00b61072016-10-19 23:22:5122
Vitaly Buka9dd2f8e2017-01-13 08:48:3123#include "src/field_instance.h"
Vitaly Bukaaf8136f2017-06-09 23:40:1224#include "src/utf8_fix.h"
Vitaly Buka9dd2f8e2017-01-13 08:48:3125#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 23:22:5126
Vitaly Bukaf86815c2017-02-27 22:19:1927namespace protobuf_mutator {
28
Vitaly Buka6c6dbbe2017-02-22 21:58:2429using protobuf::Descriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2430using protobuf::FieldDescriptor;
Vitaly Buka796b1122017-03-03 22:42:0231using protobuf::FileDescriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2432using protobuf::Message;
33using protobuf::OneofDescriptor;
34using protobuf::Reflection;
Vitaly Buka4782c142017-03-04 08:12:3235using protobuf::util::MessageDifferencer;
Vitaly Buka796b1122017-03-03 22:42:0236using std::placeholders::_1;
Vitaly Buka0e17fd72016-11-18 18:02:4637
38namespace {
39
Vitaly Bukae4eae602017-09-29 00:28:1240const int kMaxInitializeDepth = 200;
Vitaly Buka329fa462017-03-15 23:52:1741const uint64_t kDefaultMutateWeight = 1000000;
Vitaly Buka0e17fd72016-11-18 18:02:4642
43enum class Mutation {
Vitaly Buka30de3092016-11-18 19:39:0744 None,
Vitaly Buka4af611d2016-12-04 02:57:3245 Add, // Adds new field with default value.
46 Mutate, // Mutates field contents.
47 Delete, // Deletes field.
Vitaly Bukaa3e59c72016-12-07 00:53:5648 Copy, // Copy values copied from another field.
Vitaly Buka4af611d2016-12-04 02:57:3249
Vitaly Buka432b5452016-12-09 22:42:0950 // TODO(vitalybuka):
51 // Clone, // Adds new field with value copied from another field.
Vitaly Buka0e17fd72016-11-18 18:02:4652};
53
Vitaly Bukab592ff02017-03-03 22:35:5254// Return random integer from [0, count)
Vitaly Bukaf62fe472017-03-02 07:05:1555size_t GetRandomIndex(RandomEngine* random, size_t count) {
Vitaly Bukab592ff02017-03-03 22:35:5256 assert(count > 0);
57 if (count == 1) return 0;
58 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
59}
60
Vitaly Buka4af611d2016-12-04 02:57:3261// Flips random bit in the buffer.
Vitaly Bukaf62fe472017-03-02 07:05:1562void FlipBit(size_t size, uint8_t* bytes, RandomEngine* random) {
Vitaly Bukab592ff02017-03-03 22:35:5263 size_t bit = GetRandomIndex(random, size * 8);
Vitaly Buka4af611d2016-12-04 02:57:3264 bytes[bit / 8] ^= (1u << (bit % 8));
65}
Vitaly Buka781853c2016-11-22 07:09:3566
Vitaly Buka4af611d2016-12-04 02:57:3267// Flips random bit in the value.
68template <class T>
Vitaly Bukaf62fe472017-03-02 07:05:1569T FlipBit(T value, RandomEngine* random) {
Vitaly Buka4af611d2016-12-04 02:57:3270 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
71 return value;
72}
Vitaly Buka781853c2016-11-22 07:09:3573
Vitaly Bukabeb90802017-02-28 23:28:1074// Return true with probability about 1-of-n.
Vitaly Bukaf62fe472017-03-02 07:05:1575bool GetRandomBool(RandomEngine* random, size_t n = 2) {
Vitaly Bukabeb90802017-02-28 23:28:1076 return GetRandomIndex(random, n) == 0;
77}
78
Vitaly Buka28ca0ee2017-03-05 05:35:4279bool IsProto3SimpleField(const FieldDescriptor& field) {
80 assert(field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
81 field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2);
82 return field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
83 field.cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
84 !field.containing_oneof() && !field.is_repeated();
85}
86
Vitaly Bukad4ab1e72017-03-04 07:51:1987struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
Vitaly Buka91ad7b02016-12-12 23:41:4188 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:1989 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:4190 T value;
91 field.GetDefault(&value);
92 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:3293 }
Vitaly Buka91ad7b02016-12-12 23:41:4194};
Vitaly Bukabec52222016-12-09 22:29:3295
Vitaly Bukad4ab1e72017-03-04 07:51:1996struct DeleteField : public FieldFunction<DeleteField> {
Vitaly Buka91ad7b02016-12-12 23:41:4197 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:1998 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:4199 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:32100 }
Vitaly Bukabec52222016-12-09 22:29:32101};
102
Vitaly Bukad4ab1e72017-03-04 07:51:19103struct CopyField : public FieldFunction<CopyField> {
Vitaly Bukaa3e59c72016-12-07 00:53:56104 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19105 void ForType(const ConstFieldInstance& source,
106 const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:56107 T value;
108 source.Load(&value);
109 field.Store(value);
110 }
Vitaly Bukaa3e59c72016-12-07 00:53:56111};
112
Vitaly Bukad4ab1e72017-03-04 07:51:19113struct AppendField : public FieldFunction<AppendField> {
Vitaly Bukaadfc27c2017-02-27 06:36:36114 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19115 void ForType(const ConstFieldInstance& source,
116 const FieldInstance& field) const {
Vitaly Bukaadfc27c2017-02-27 06:36:36117 T value;
118 source.Load(&value);
119 field.Create(value);
120 }
Vitaly Bukaadfc27c2017-02-27 06:36:36121};
122
Vitaly Buka2792ed72019-01-23 19:04:24123class CanCopyAndDifferentField
124 : public FieldFunction<CanCopyAndDifferentField, bool> {
Vitaly Buka4782c142017-03-04 08:12:32125 public:
126 template <class T>
Vitaly Buka5cd166e2020-01-26 06:33:05127 bool ForType(const ConstFieldInstance& src, const ConstFieldInstance& dst,
128 int size_increase_hint) const {
Vitaly Buka2792ed72019-01-23 19:04:24129 T s;
130 src.Load(&s);
131 if (!dst.CanStore(s)) return false;
132 T d;
133 dst.Load(&d);
Vitaly Buka5cd166e2020-01-26 06:33:05134 return SizeDiff(s, d) <= size_increase_hint && !IsEqual(s, d);
Vitaly Buka4782c142017-03-04 08:12:32135 }
136
137 private:
138 bool IsEqual(const ConstFieldInstance::Enum& a,
139 const ConstFieldInstance::Enum& b) const {
140 assert(a.count == b.count);
141 return a.index == b.index;
142 }
143
144 bool IsEqual(const std::unique_ptr<protobuf::Message>& a,
145 const std::unique_ptr<protobuf::Message>& b) const {
146 return MessageDifferencer::Equals(*a, *b);
147 }
148
149 template <class T>
150 bool IsEqual(const T& a, const T& b) const {
151 return a == b;
152 }
Vitaly Buka5cd166e2020-01-26 06:33:05153
154 int64_t SizeDiff(const std::unique_ptr<protobuf::Message>& src,
155 const std::unique_ptr<protobuf::Message>& dst) const {
156 return src->ByteSizeLong() - dst->ByteSizeLong();
157 }
158
159 int64_t SizeDiff(const std::string& src, const std::string& dst) const {
160 return src.size() - dst.size();
161 }
162
163 template <class T>
164 int64_t SizeDiff(const T&, const T&) const {
165 return 0;
166 }
Vitaly Buka4782c142017-03-04 08:12:32167};
168
Vitaly Buka4af611d2016-12-04 02:57:32169// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35170class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17171 public:
Vitaly Buka4908d252020-01-25 03:10:34172 MutationSampler(bool keep_initialized, bool can_grow, RandomEngine* random,
173 Message* message)
174 : keep_initialized_(keep_initialized),
175 can_grow_(can_grow),
176 random_(random),
177 sampler_(random) {
Vitaly Buka781853c2016-11-22 07:09:35178 Sample(message);
Vitaly Buka4908d252020-01-25 03:10:34179 assert(mutation() != Mutation::None || !can_grow ||
Vitaly Bukaf3383a92017-03-20 00:04:18180 message->GetDescriptor()->field_count() == 0);
Vitaly Bukac9d22482016-11-21 21:29:17181 }
182
Vitaly Buka4af611d2016-12-04 02:57:32183 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32184 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32185
186 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09187 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32188
189 private:
Vitaly Buka781853c2016-11-22 07:09:35190 void Sample(Message* message) {
191 const Descriptor* descriptor = message->GetDescriptor();
192 const Reflection* reflection = message->GetReflection();
193
194 int field_count = descriptor->field_count();
195 for (int i = 0; i < field_count; ++i) {
196 const FieldDescriptor* field = descriptor->field(i);
197 if (const OneofDescriptor* oneof = field->containing_oneof()) {
198 // Handle entire oneof group on the first field.
199 if (field->index_in_oneof() == 0) {
Vitaly Buka2f660a52017-03-04 03:46:14200 assert(oneof->field_count());
201 const FieldDescriptor* current_field =
202 reflection->GetOneofFieldDescriptor(*message, oneof);
203 for (;;) {
204 const FieldDescriptor* add_field =
205 oneof->field(GetRandomIndex(random_, oneof->field_count()));
206 if (add_field != current_field) {
Vitaly Buka4908d252020-01-25 03:10:34207 Try({message, add_field}, Mutation::Add);
Vitaly Buka2f660a52017-03-04 03:46:14208 break;
209 }
210 if (oneof->field_count() < 2) break;
211 }
212 if (current_field) {
Vitaly Buka4908d252020-01-25 03:10:34213 if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
214 Try({message, current_field}, Mutation::Mutate);
215 Try({message, current_field}, Mutation::Delete);
216 Try({message, current_field}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35217 }
218 }
219 } else {
220 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32221 int field_size = reflection->FieldSize(*message, field);
Vitaly Buka4908d252020-01-25 03:10:34222 Try({message, field, GetRandomIndex(random_, field_size + 1)},
223 Mutation::Add);
Vitaly Buka781853c2016-11-22 07:09:35224
Vitaly Bukabec52222016-12-09 22:29:32225 if (field_size) {
226 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka4908d252020-01-25 03:10:34227 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
228 Try({message, field, random_index}, Mutation::Mutate);
229 Try({message, field, random_index}, Mutation::Delete);
230 Try({message, field, random_index}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35231 }
232 } else {
Vitaly Buka28ca0ee2017-03-05 05:35:42233 if (reflection->HasField(*message, field) ||
234 IsProto3SimpleField(*field)) {
Vitaly Buka4908d252020-01-25 03:10:34235 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
236 Try({message, field}, Mutation::Mutate);
Vitaly Buka28ca0ee2017-03-05 05:35:42237 if (!IsProto3SimpleField(*field) &&
238 (!field->is_required() || !keep_initialized_)) {
Vitaly Buka4908d252020-01-25 03:10:34239 Try({message, field}, Mutation::Delete);
Vitaly Buka28ca0ee2017-03-05 05:35:42240 }
Vitaly Buka4908d252020-01-25 03:10:34241 Try({message, field}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35242 } else {
Vitaly Buka4908d252020-01-25 03:10:34243 Try({message, field}, Mutation::Add);
Vitaly Buka781853c2016-11-22 07:09:35244 }
245 }
246 }
247
248 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
249 if (field->is_repeated()) {
250 const int field_size = reflection->FieldSize(*message, field);
251 for (int j = 0; j < field_size; ++j)
252 Sample(reflection->MutableRepeatedMessage(message, field, j));
253 } else if (reflection->HasField(*message, field)) {
254 Sample(reflection->MutableMessage(message, field));
255 }
256 }
257 }
258 }
259
Vitaly Buka4908d252020-01-25 03:10:34260 void Try(const FieldInstance& field, Mutation mutation) {
261 assert(mutation != Mutation::None);
262 if (!can_grow_ && mutation != Mutation::Delete) return;
263 sampler_.Try(kDefaultMutateWeight, {field, mutation});
264 }
265
Vitaly Buka781853c2016-11-22 07:09:35266 bool keep_initialized_ = false;
Vitaly Buka4908d252020-01-25 03:10:34267 bool can_grow_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32268
Vitaly Bukaf62fe472017-03-02 07:05:15269 RandomEngine* random_;
Vitaly Buka4af611d2016-12-04 02:57:32270
271 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41272 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32273 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41274
Vitaly Bukabec52222016-12-09 22:29:32275 FieldInstance field;
276 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32277 };
Vitaly Bukaf62fe472017-03-02 07:05:15278 WeightedReservoirSampler<Result, RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17279};
280
Vitaly Bukaa3e59c72016-12-07 00:53:56281// Selects random field of compatible type to use for clone mutations.
282class DataSourceSampler {
283 public:
Vitaly Bukaf62fe472017-03-02 07:05:15284 DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
Vitaly Buka5cd166e2020-01-26 06:33:05285 int size_increase_hint, const Message& message)
286 : match_(match),
287 random_(random),
288 size_increase_hint_(size_increase_hint),
289 sampler_(random) {
Vitaly Bukaa3e59c72016-12-07 00:53:56290 Sample(message);
291 }
292
293 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30294 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24295 assert(!IsEmpty());
296 return sampler_.selected();
297 }
298
299 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56300
301 private:
Vitaly Buka0f63f912020-01-24 23:02:45302 void Sample(const Message& message) {
303 const Descriptor* descriptor = message.GetDescriptor();
304 const Reflection* reflection = message.GetReflection();
Vitaly Bukaa3e59c72016-12-07 00:53:56305
306 int field_count = descriptor->field_count();
307 for (int i = 0; i < field_count; ++i) {
308 const FieldDescriptor* field = descriptor->field(i);
309 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
310 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45311 const int field_size = reflection->FieldSize(message, field);
Vitaly Bukaa3e59c72016-12-07 00:53:56312 for (int j = 0; j < field_size; ++j) {
Vitaly Buka0f63f912020-01-24 23:02:45313 Sample(reflection->GetRepeatedMessage(message, field, j));
Vitaly Bukaa3e59c72016-12-07 00:53:56314 }
Vitaly Buka0f63f912020-01-24 23:02:45315 } else if (reflection->HasField(message, field)) {
316 Sample(reflection->GetMessage(message, field));
Vitaly Bukaa3e59c72016-12-07 00:53:56317 }
318 }
319
320 if (field->cpp_type() != match_.cpp_type()) continue;
321 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
322 if (field->enum_type() != match_.enum_type()) continue;
323 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
324 if (field->message_type() != match_.message_type()) continue;
325 }
326
Vitaly Bukaa3e59c72016-12-07 00:53:56327 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45328 if (int field_size = reflection->FieldSize(message, field)) {
329 ConstFieldInstance source(&message, field,
Vitaly Buka4782c142017-03-04 08:12:32330 GetRandomIndex(random_, field_size));
Vitaly Buka5cd166e2020-01-26 06:33:05331 if (CanCopyAndDifferentField()(source, match_, size_increase_hint_))
Vitaly Buka4782c142017-03-04 08:12:32332 sampler_.Try(field_size, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56333 }
334 } else {
Vitaly Buka0f63f912020-01-24 23:02:45335 if (reflection->HasField(message, field)) {
336 ConstFieldInstance source(&message, field);
Vitaly Buka5cd166e2020-01-26 06:33:05337 if (CanCopyAndDifferentField()(source, match_, size_increase_hint_))
Vitaly Buka2792ed72019-01-23 19:04:24338 sampler_.Try(1, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56339 }
340 }
341 }
342 }
343
Vitaly Buka88712862017-02-27 06:21:30344 ConstFieldInstance match_;
Vitaly Bukaf62fe472017-03-02 07:05:15345 RandomEngine* random_;
Vitaly Buka5cd166e2020-01-26 06:33:05346 int size_increase_hint_;
Vitaly Bukaa3e59c72016-12-07 00:53:56347
Vitaly Bukaf62fe472017-03-02 07:05:15348 WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56349};
350
Vitaly Buka0e17fd72016-11-18 18:02:46351} // namespace
352
Vitaly Buka5d013202017-02-25 00:50:11353class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09354 public:
Vitaly Buka1c91e722020-01-26 05:56:22355 FieldMutator(int size_increase_hint, bool enforce_changes,
Vitaly Buka0f63f912020-01-24 23:02:45356 bool enforce_utf8_strings, const protobuf::Message& source,
357 Mutator* mutator)
Vitaly Buka0e9439f2017-03-16 00:51:57358 : size_increase_hint_(size_increase_hint),
359 enforce_changes_(enforce_changes),
Vitaly Bukaaf8136f2017-06-09 23:40:12360 enforce_utf8_strings_(enforce_utf8_strings),
Vitaly Buka0f63f912020-01-24 23:02:45361 source_(source),
Vitaly Buka0e9439f2017-03-16 00:51:57362 mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41363
Vitaly Buka796b1122017-03-03 22:42:02364 void Mutate(int32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14365 RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02366 }
Vitaly Buka91ad7b02016-12-12 23:41:41367
Vitaly Buka796b1122017-03-03 22:42:02368 void Mutate(int64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14369 RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02370 }
Vitaly Buka91ad7b02016-12-12 23:41:41371
372 void Mutate(uint32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14373 RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41374 }
375
376 void Mutate(uint64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14377 RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41378 }
379
Vitaly Buka796b1122017-03-03 22:42:02380 void Mutate(float* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14381 RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02382 }
Vitaly Buka91ad7b02016-12-12 23:41:41383
Vitaly Buka796b1122017-03-03 22:42:02384 void Mutate(double* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14385 RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02386 }
Vitaly Buka91ad7b02016-12-12 23:41:41387
Vitaly Buka796b1122017-03-03 22:42:02388 void Mutate(bool* value) const {
Vitaly Bukad7f943f2019-01-31 22:05:33389 RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02390 }
Vitaly Buka91ad7b02016-12-12 23:41:41391
392 void Mutate(FieldInstance::Enum* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14393 RepeatMutate(&value->index,
Vitaly Bukad7f943f2019-01-31 22:05:33394 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count));
Vitaly Buka91ad7b02016-12-12 23:41:41395 assert(value->index < value->count);
396 }
397
398 void Mutate(std::string* value) const {
Vitaly Bukaaf8136f2017-06-09 23:40:12399 if (enforce_utf8_strings_) {
400 RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1,
401 size_increase_hint_));
402 } else {
403 RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
404 size_increase_hint_));
405 }
Vitaly Buka91ad7b02016-12-12 23:41:41406 }
407
Vitaly Bukab2c4fb52017-03-16 18:50:40408 void Mutate(std::unique_ptr<Message>* message) const {
409 assert(!enforce_changes_);
410 assert(*message);
Vitaly Bukad7f943f2019-01-31 22:05:33411 if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_))
412 return;
Vitaly Buka0f63f912020-01-24 23:02:45413 mutator_->MutateImpl(source_, message->get(), size_increase_hint_);
Vitaly Bukab2c4fb52017-03-16 18:50:40414 }
Vitaly Buka432b5452016-12-09 22:42:09415
Vitaly Buka5d013202017-02-25 00:50:11416 private:
Vitaly Buka796b1122017-03-03 22:42:02417 template <class T, class F>
Vitaly Bukad7f943f2019-01-31 22:05:33418 void RepeatMutate(T* value, F mutate) const {
Vitaly Buka0e9439f2017-03-16 00:51:57419 if (!enforce_changes_ &&
Vitaly Bukad7f943f2019-01-31 22:05:33420 GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) {
Vitaly Buka0e9439f2017-03-16 00:51:57421 return;
Vitaly Bukab2c4fb52017-03-16 18:50:40422 }
Vitaly Buka796b1122017-03-03 22:42:02423 T tmp = *value;
424 for (int i = 0; i < 10; ++i) {
425 *value = mutate(*value);
Vitaly Buka0e9439f2017-03-16 00:51:57426 if (!enforce_changes_ || *value != tmp) return;
Vitaly Buka796b1122017-03-03 22:42:02427 }
428 }
429
Vitaly Buka1c91e722020-01-26 05:56:22430 int size_increase_hint_;
Vitaly Buka0e9439f2017-03-16 00:51:57431 size_t enforce_changes_;
Vitaly Bukaaf8136f2017-06-09 23:40:12432 bool enforce_utf8_strings_;
Vitaly Buka0f63f912020-01-24 23:02:45433 const protobuf::Message& source_;
Vitaly Bukae79e0182017-03-02 00:02:14434 Mutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09435};
436
Vitaly Buka5d013202017-02-25 00:50:11437namespace {
438
Vitaly Bukad4ab1e72017-03-04 07:51:19439struct MutateField : public FieldFunction<MutateField> {
Vitaly Buka5d013202017-02-25 00:50:11440 template <class T>
Vitaly Buka1c91e722020-01-26 05:56:22441 void ForType(const FieldInstance& field, int size_increase_hint,
Vitaly Buka0f63f912020-01-24 23:02:45442 const protobuf::Message& source, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11443 T value;
444 field.Load(&value);
Vitaly Buka0f63f912020-01-24 23:02:45445 FieldMutator(size_increase_hint, true, field.EnforceUtf8(), source, mutator)
Vitaly Bukaaf8136f2017-06-09 23:40:12446 .Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11447 field.Store(value);
448 }
Vitaly Buka5d013202017-02-25 00:50:11449};
450
Vitaly Bukad4ab1e72017-03-04 07:51:19451struct CreateField : public FieldFunction<CreateField> {
Vitaly Buka5d013202017-02-25 00:50:11452 public:
Vitaly Buka5d013202017-02-25 00:50:11453 template <class T>
Vitaly Buka1c91e722020-01-26 05:56:22454 void ForType(const FieldInstance& field, int size_increase_hint,
Vitaly Buka0f63f912020-01-24 23:02:45455 const protobuf::Message& source, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11456 T value;
457 field.GetDefault(&value);
Vitaly Buka0e9439f2017-03-16 00:51:57458 FieldMutator field_mutator(size_increase_hint,
Vitaly Bukaaf8136f2017-06-09 23:40:12459 false /* defaults could be useful */,
Vitaly Buka0f63f912020-01-24 23:02:45460 field.EnforceUtf8(), source, mutator);
Vitaly Buka0e9439f2017-03-16 00:51:57461 field_mutator.Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11462 field.Create(value);
463 }
Vitaly Buka5d013202017-02-25 00:50:11464};
465
466} // namespace
467
Vitaly Buka379f5ab2019-08-31 23:11:59468void Mutator::Seed(uint32_t value) { random_.seed(value); }
Vitaly Buka432b5452016-12-09 22:42:09469
Vitaly Bukabaa13292020-01-26 03:39:28470void Mutator::Mutate(Message* message, size_t max_size_hint) {
471 MutateImpl(*message, message,
Vitaly Buka1c91e722020-01-26 05:56:22472 static_cast<int>(max_size_hint) -
473 static_cast<int>(message->ByteSizeLong()));
Vitaly Buka0e17fd72016-11-18 18:02:46474
Vitaly Bukae4eae602017-09-29 00:28:12475 InitializeAndTrim(message, kMaxInitializeDepth);
Vitaly Buka9eaf0632020-01-16 01:30:20476 assert(IsInitialized(*message));
Vitaly Buka67387f72019-09-01 02:34:10477
Peter Foleyfe76ed62019-10-01 00:03:37478 if (!post_processors_.empty()) {
479 ApplyPostProcessing(message);
480 }
481}
482
483void Mutator::RegisterPostProcessor(const protobuf::Descriptor* desc,
484 PostProcess callback) {
485 post_processors_.emplace(desc, callback);
486}
487
488void Mutator::ApplyPostProcessing(Message* message) {
489 const Descriptor* descriptor = message->GetDescriptor();
490
Vitaly Bukaad520b32020-01-08 22:39:55491 auto range = post_processors_.equal_range(descriptor);
492 for (auto it = range.first; it != range.second; ++it)
Peter Foleyfe76ed62019-10-01 00:03:37493 it->second(message, random_());
Peter Foleyfe76ed62019-10-01 00:03:37494
495 // Now recursively apply custom mutators.
496 const Reflection* reflection = message->GetReflection();
497 for (int i = 0; i < descriptor->field_count(); i++) {
498 const FieldDescriptor* field = descriptor->field(i);
499 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
500 continue;
501 }
502 if (field->is_repeated()) {
503 const int field_size = reflection->FieldSize(*message, field);
504 for (int j = 0; j < field_size; ++j) {
505 Message* nested_message =
506 reflection->MutableRepeatedMessage(message, field, j);
507 ApplyPostProcessing(nested_message);
508 }
509 } else if (reflection->HasField(*message, field)) {
510 Message* nested_message = reflection->MutableMessage(message, field);
511 ApplyPostProcessing(nested_message);
512 }
513 }
Vitaly Buka00b61072016-10-19 23:22:51514}
515
Vitaly Buka0f63f912020-01-24 23:02:45516void Mutator::MutateImpl(const Message& source, Message* message,
Vitaly Buka1c91e722020-01-26 05:56:22517 int size_increase_hint) {
518 if (size_increase_hint > 0) size_increase_hint /= 2;
Vitaly Buka3183b0d2019-09-06 22:11:10519 for (;;) {
Vitaly Buka5cd166e2020-01-26 06:33:05520 MutationSampler mutation(keep_initialized_, size_increase_hint > 16,
Vitaly Buka1c91e722020-01-26 05:56:22521 &random_, message);
Vitaly Buka3183b0d2019-09-06 22:11:10522 switch (mutation.mutation()) {
523 case Mutation::None:
524 return;
525 case Mutation::Add:
Vitaly Buka4908d252020-01-25 03:10:34526 CreateField()(mutation.field(), size_increase_hint, source, this);
Vitaly Buka3183b0d2019-09-06 22:11:10527 return;
528 case Mutation::Mutate:
Vitaly Buka4908d252020-01-25 03:10:34529 MutateField()(mutation.field(), size_increase_hint, source, this);
Vitaly Buka3183b0d2019-09-06 22:11:10530 return;
531 case Mutation::Delete:
532 DeleteField()(mutation.field());
533 return;
534 case Mutation::Copy: {
Vitaly Buka5cd166e2020-01-26 06:33:05535 DataSourceSampler source_sampler(mutation.field(), &random_,
536 size_increase_hint, source);
Vitaly Buka0f63f912020-01-24 23:02:45537 if (source_sampler.IsEmpty()) break;
538 CopyField()(source_sampler.field(), mutation.field());
Vitaly Buka3183b0d2019-09-06 22:11:10539 return;
540 }
541 default:
542 assert(false && "unexpected mutation");
543 return;
544 }
545 }
546}
547
Vitaly Bukae79e0182017-03-02 00:02:14548void Mutator::CrossOver(const protobuf::Message& message1,
549 protobuf::Message* message2) {
Vitaly Buka142e08b2017-03-06 00:26:15550 // CrossOver can produce result which still equals to inputs. So we backup
551 // message2 to later comparison. message1 is already constant.
552 std::unique_ptr<protobuf::Message> message2_copy(message2->New());
553 message2_copy->CopyFrom(*message2);
554
Vitaly Bukaadfc27c2017-02-27 06:36:36555 CrossOverImpl(message1, message2);
556
Vitaly Bukae4eae602017-09-29 00:28:12557 InitializeAndTrim(message2, kMaxInitializeDepth);
Vitaly Buka9eaf0632020-01-16 01:30:20558 assert(IsInitialized(*message2));
Vitaly Buka142e08b2017-03-06 00:26:15559
Vitaly Bukadd89da92019-10-08 17:08:02560 if (!post_processors_.empty()) {
561 ApplyPostProcessing(message2);
562 }
Vitaly Buka67387f72019-09-01 02:34:10563
Vitaly Buka2d609df2017-03-07 07:29:47564 // Can't call mutate from crossover because of a bug in libFuzzer.
Vitaly Buka2d609df2017-03-07 07:29:47565 // if (MessageDifferencer::Equals(*message2_copy, *message2) ||
566 // MessageDifferencer::Equals(message1, *message2)) {
567 // Mutate(message2, 0);
568 // }
Vitaly Bukaadfc27c2017-02-27 06:36:36569}
570
Vitaly Bukae79e0182017-03-02 00:02:14571void Mutator::CrossOverImpl(const protobuf::Message& message1,
572 protobuf::Message* message2) {
Vitaly Bukaadfc27c2017-02-27 06:36:36573 const Descriptor* descriptor = message2->GetDescriptor();
574 const Reflection* reflection = message2->GetReflection();
575 assert(message1.GetDescriptor() == descriptor);
576 assert(message1.GetReflection() == reflection);
577
578 for (int i = 0; i < descriptor->field_count(); ++i) {
579 const FieldDescriptor* field = descriptor->field(i);
580
581 if (field->is_repeated()) {
582 const int field_size1 = reflection->FieldSize(message1, field);
583 int field_size2 = reflection->FieldSize(*message2, field);
584 for (int j = 0; j < field_size1; ++j) {
585 ConstFieldInstance source(&message1, field, j);
586 FieldInstance destination(message2, field, field_size2++);
Vitaly Bukad4ab1e72017-03-04 07:51:19587 AppendField()(source, destination);
Vitaly Bukaadfc27c2017-02-27 06:36:36588 }
589
590 assert(field_size2 == reflection->FieldSize(*message2, field));
591
592 // Shuffle
593 for (int j = 0; j < field_size2; ++j) {
Vitaly Buka379f5ab2019-08-31 23:11:59594 if (int k = GetRandomIndex(&random_, field_size2 - j)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36595 reflection->SwapElements(message2, field, j, j + k);
596 }
597 }
598
Vitaly Buka379f5ab2019-08-31 23:11:59599 int keep = GetRandomIndex(&random_, field_size2 + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36600
601 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
602 int remove = field_size2 - keep;
603 // Cross some message to keep with messages to remove.
Vitaly Buka379f5ab2019-08-31 23:11:59604 int cross = GetRandomIndex(&random_, std::min(keep, remove) + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36605 for (int j = 0; j < cross; ++j) {
Vitaly Buka379f5ab2019-08-31 23:11:59606 int k = GetRandomIndex(&random_, keep);
607 int r = keep + GetRandomIndex(&random_, remove);
Vitaly Bukaadfc27c2017-02-27 06:36:36608 assert(k != r);
609 CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
610 reflection->MutableRepeatedMessage(message2, field, k));
611 }
612 }
613
614 for (int j = keep; j < field_size2; ++j)
615 reflection->RemoveLast(message2, field);
616 assert(keep == reflection->FieldSize(*message2, field));
617
618 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
619 if (!reflection->HasField(message1, field)) {
Vitaly Buka379f5ab2019-08-31 23:11:59620 if (GetRandomBool(&random_))
Vitaly Bukad4ab1e72017-03-04 07:51:19621 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36622 } else if (!reflection->HasField(*message2, field)) {
Vitaly Buka379f5ab2019-08-31 23:11:59623 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36624 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19625 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36626 }
627 } else {
628 CrossOverImpl(reflection->GetMessage(message1, field),
629 reflection->MutableMessage(message2, field));
630 }
631 } else {
Vitaly Buka379f5ab2019-08-31 23:11:59632 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36633 if (reflection->HasField(message1, field)) {
634 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19635 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36636 } else {
Vitaly Bukad4ab1e72017-03-04 07:51:19637 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36638 }
639 }
640 }
641 }
642}
643
Vitaly Bukae4eae602017-09-29 00:28:12644void Mutator::InitializeAndTrim(Message* message, int max_depth) {
Vitaly Buka13245af2016-11-18 21:20:12645 const Descriptor* descriptor = message->GetDescriptor();
646 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12647 for (int i = 0; i < descriptor->field_count(); ++i) {
648 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka4200a1e2019-07-29 22:19:59649 if (keep_initialized_ &&
650 (field->is_required() || descriptor->options().map_entry()) &&
651 !reflection->HasField(*message, field)) {
Vitaly Bukad4ab1e72017-03-04 07:51:19652 CreateDefaultField()(FieldInstance(message, field));
Vitaly Buka4200a1e2019-07-29 22:19:59653 }
Vitaly Buka13245af2016-11-18 21:20:12654
Vitaly Bukae4eae602017-09-29 00:28:12655 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
656 if (max_depth <= 0 && !field->is_required()) {
657 // Clear deep optional fields to avoid stack overflow.
658 reflection->ClearField(message, field);
659 if (field->is_repeated())
660 assert(!reflection->FieldSize(*message, field));
661 else
662 assert(!reflection->HasField(*message, field));
663 continue;
664 }
665
Vitaly Buka2cfe02b2016-11-19 00:34:09666 if (field->is_repeated()) {
667 const int field_size = reflection->FieldSize(*message, field);
668 for (int j = 0; j < field_size; ++j) {
669 Message* nested_message =
670 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Bukae4eae602017-09-29 00:28:12671 InitializeAndTrim(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09672 }
673 } else if (reflection->HasField(*message, field)) {
674 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Bukae4eae602017-09-29 00:28:12675 InitializeAndTrim(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12676 }
677 }
678 }
679}
Vitaly Buka4af611d2016-12-04 02:57:32680
Vitaly Buka379f5ab2019-08-31 23:11:59681int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14682
Vitaly Buka379f5ab2019-08-31 23:11:59683int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14684
685uint32_t Mutator::MutateUInt32(uint32_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59686 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32687}
688
Vitaly Bukae79e0182017-03-02 00:02:14689uint64_t Mutator::MutateUInt64(uint64_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59690 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32691}
692
Vitaly Buka379f5ab2019-08-31 23:11:59693float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32694
Vitaly Buka379f5ab2019-08-31 23:11:59695double Mutator::MutateDouble(double value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32696
Vitaly Bukae79e0182017-03-02 00:02:14697bool Mutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-04 02:57:32698
Vitaly Bukae79e0182017-03-02 00:02:14699size_t Mutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukaee1c76a2017-03-15 17:48:53700 if (item_count <= 1) return 0;
Vitaly Buka379f5ab2019-08-31 23:11:59701 return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-04 02:57:32702}
703
Vitaly Bukae79e0182017-03-02 00:02:14704std::string Mutator::MutateString(const std::string& value,
Vitaly Buka1c91e722020-01-26 05:56:22705 int size_increase_hint) {
Vitaly Buka4af611d2016-12-04 02:57:32706 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11707
Vitaly Buka379f5ab2019-08-31 23:11:59708 while (!result.empty() && GetRandomBool(&random_)) {
709 result.erase(GetRandomIndex(&random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09710 }
711
Vitaly Buka1c91e722020-01-26 05:56:22712 while (size_increase_hint > 0 &&
713 result.size() < static_cast<size_t>(size_increase_hint) &&
714 GetRandomBool(&random_)) {
Vitaly Buka379f5ab2019-08-31 23:11:59715 size_t index = GetRandomIndex(&random_, result.size() + 1);
716 result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09717 }
718
Vitaly Bukac020de12017-03-04 03:36:23719 if (result != value) return result;
720
721 if (result.empty()) {
Vitaly Buka379f5ab2019-08-31 23:11:59722 result.push_back(GetRandomIndex(&random_, 1 << 8));
Vitaly Bukac020de12017-03-04 03:36:23723 return result;
724 }
725
Vitaly Buka4af611d2016-12-04 02:57:32726 if (!result.empty())
Vitaly Buka379f5ab2019-08-31 23:11:59727 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
Vitaly Buka4af611d2016-12-04 02:57:32728 return result;
729}
Vitaly Buka432b5452016-12-09 22:42:09730
Vitaly Bukaaf8136f2017-06-09 23:40:12731std::string Mutator::MutateUtf8String(const std::string& value,
Vitaly Buka1c91e722020-01-26 05:56:22732 int size_increase_hint) {
Vitaly Bukaaf8136f2017-06-09 23:40:12733 std::string str = MutateString(value, size_increase_hint);
Vitaly Buka379f5ab2019-08-31 23:11:59734 FixUtf8String(&str, &random_);
Vitaly Bukaaf8136f2017-06-09 23:40:12735 return str;
736}
737
Vitaly Buka9eaf0632020-01-16 01:30:20738bool Mutator::IsInitialized(const Message& message) const {
739 if (!keep_initialized_ || message.IsInitialized()) return true;
740 std::cerr << "Uninitialized: " << message.DebugString() << "\n";
741 return false;
742}
743
Vitaly Buka432b5452016-12-09 22:42:09744} // namespace protobuf_mutator