blob: 2aa9693935b4193e4c620984cfbce96020dd9aeb [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>
Tomáš Popela17789d12017-08-15 11:41:5918#include <functional>
Vitaly Buka0e17fd72016-11-18 18:02:4619#include <map>
Vitaly Buka781853c2016-11-22 07:09:3520#include <random>
Vitaly Buka0e17fd72016-11-18 18:02:4621#include <string>
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 Buka4782c142017-03-04 08:12:32123class IsEqualValueField : public FieldFunction<IsEqualValueField, bool> {
124 public:
125 template <class T>
126 bool ForType(const ConstFieldInstance& a, const ConstFieldInstance& b) const {
127 T aa;
128 a.Load(&aa);
129 T bb;
130 b.Load(&bb);
131 return IsEqual(aa, bb);
132 }
133
134 private:
135 bool IsEqual(const ConstFieldInstance::Enum& a,
136 const ConstFieldInstance::Enum& b) const {
137 assert(a.count == b.count);
138 return a.index == b.index;
139 }
140
141 bool IsEqual(const std::unique_ptr<protobuf::Message>& a,
142 const std::unique_ptr<protobuf::Message>& b) const {
143 return MessageDifferencer::Equals(*a, *b);
144 }
145
146 template <class T>
147 bool IsEqual(const T& a, const T& b) const {
148 return a == b;
149 }
150};
151
Vitaly Buka4af611d2016-12-04 02:57:32152// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35153class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17154 public:
Vitaly Buka329fa462017-03-15 23:52:17155 MutationSampler(bool keep_initialized, RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-04 02:57:32156 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka781853c2016-11-22 07:09:35157 Sample(message);
Vitaly Bukaf3383a92017-03-20 00:04:18158 assert(mutation() != Mutation::None ||
159 message->GetDescriptor()->field_count() == 0);
Vitaly Bukac9d22482016-11-21 21:29:17160 }
161
Vitaly Buka4af611d2016-12-04 02:57:32162 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32163 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32164
165 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09166 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32167
168 private:
Vitaly Buka781853c2016-11-22 07:09:35169 void Sample(Message* message) {
170 const Descriptor* descriptor = message->GetDescriptor();
171 const Reflection* reflection = message->GetReflection();
172
173 int field_count = descriptor->field_count();
174 for (int i = 0; i < field_count; ++i) {
175 const FieldDescriptor* field = descriptor->field(i);
176 if (const OneofDescriptor* oneof = field->containing_oneof()) {
177 // Handle entire oneof group on the first field.
178 if (field->index_in_oneof() == 0) {
Vitaly Buka2f660a52017-03-04 03:46:14179 assert(oneof->field_count());
180 const FieldDescriptor* current_field =
181 reflection->GetOneofFieldDescriptor(*message, oneof);
182 for (;;) {
183 const FieldDescriptor* add_field =
184 oneof->field(GetRandomIndex(random_, oneof->field_count()));
185 if (add_field != current_field) {
Vitaly Buka329fa462017-03-15 23:52:17186 sampler_.Try(kDefaultMutateWeight,
187 {{message, add_field}, Mutation::Add});
Vitaly Buka2f660a52017-03-04 03:46:14188 break;
189 }
190 if (oneof->field_count() < 2) break;
191 }
192 if (current_field) {
Vitaly Buka28ca0ee2017-03-05 05:35:42193 if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka329fa462017-03-15 23:52:17194 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14195 {{message, current_field}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42196 }
Vitaly Buka329fa462017-03-15 23:52:17197 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14198 {{message, current_field}, Mutation::Delete});
Vitaly Buka329fa462017-03-15 23:52:17199 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14200 {{message, current_field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35201 }
202 }
203 } else {
204 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32205 int field_size = reflection->FieldSize(*message, field);
Vitaly Buka329fa462017-03-15 23:52:17206 sampler_.Try(
207 kDefaultMutateWeight,
208 {{message, field, GetRandomIndex(random_, field_size + 1)},
209 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35210
Vitaly Bukabec52222016-12-09 22:29:32211 if (field_size) {
212 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka28ca0ee2017-03-05 05:35:42213 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka329fa462017-03-15 23:52:17214 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32215 {{message, field, random_index}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42216 }
Vitaly Buka329fa462017-03-15 23:52:17217 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32218 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka329fa462017-03-15 23:52:17219 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukaa3e59c72016-12-07 00:53:56220 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35221 }
222 } else {
Vitaly Buka28ca0ee2017-03-05 05:35:42223 if (reflection->HasField(*message, field) ||
224 IsProto3SimpleField(*field)) {
Vitaly Buka4af611d2016-12-04 02:57:32225 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Buka329fa462017-03-15 23:52:17226 sampler_.Try(kDefaultMutateWeight,
227 {{message, field}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42228 if (!IsProto3SimpleField(*field) &&
229 (!field->is_required() || !keep_initialized_)) {
Vitaly Buka329fa462017-03-15 23:52:17230 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32231 {{message, field}, Mutation::Delete});
Vitaly Buka28ca0ee2017-03-05 05:35:42232 }
Vitaly Buka329fa462017-03-15 23:52:17233 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka72019dc2016-12-15 03:17:24234 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35235 } else {
Vitaly Buka329fa462017-03-15 23:52:17236 sampler_.Try(kDefaultMutateWeight,
237 {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35238 }
239 }
240 }
241
242 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
243 if (field->is_repeated()) {
244 const int field_size = reflection->FieldSize(*message, field);
245 for (int j = 0; j < field_size; ++j)
246 Sample(reflection->MutableRepeatedMessage(message, field, j));
247 } else if (reflection->HasField(*message, field)) {
248 Sample(reflection->MutableMessage(message, field));
249 }
250 }
251 }
252 }
253
Vitaly Buka781853c2016-11-22 07:09:35254 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32255
Vitaly Bukaf62fe472017-03-02 07:05:15256 RandomEngine* random_;
Vitaly Buka4af611d2016-12-04 02:57:32257
258 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41259 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32260 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41261
Vitaly Bukabec52222016-12-09 22:29:32262 FieldInstance field;
263 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32264 };
Vitaly Bukaf62fe472017-03-02 07:05:15265 WeightedReservoirSampler<Result, RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17266};
267
Vitaly Bukaa3e59c72016-12-07 00:53:56268// Selects random field of compatible type to use for clone mutations.
269class DataSourceSampler {
270 public:
Vitaly Bukaf62fe472017-03-02 07:05:15271 DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
272 Message* message)
Vitaly Bukaa3e59c72016-12-07 00:53:56273 : match_(match), random_(random), sampler_(random) {
274 Sample(message);
275 }
276
277 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30278 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24279 assert(!IsEmpty());
280 return sampler_.selected();
281 }
282
283 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56284
285 private:
286 void Sample(Message* message) {
287 const Descriptor* descriptor = message->GetDescriptor();
288 const Reflection* reflection = message->GetReflection();
289
290 int field_count = descriptor->field_count();
291 for (int i = 0; i < field_count; ++i) {
292 const FieldDescriptor* field = descriptor->field(i);
293 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
294 if (field->is_repeated()) {
295 const int field_size = reflection->FieldSize(*message, field);
296 for (int j = 0; j < field_size; ++j) {
297 Sample(reflection->MutableRepeatedMessage(message, field, j));
298 }
299 } else if (reflection->HasField(*message, field)) {
300 Sample(reflection->MutableMessage(message, field));
301 }
302 }
303
304 if (field->cpp_type() != match_.cpp_type()) continue;
305 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
306 if (field->enum_type() != match_.enum_type()) continue;
307 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
308 if (field->message_type() != match_.message_type()) continue;
309 }
310
Vitaly Bukaa3e59c72016-12-07 00:53:56311 if (field->is_repeated()) {
312 if (int field_size = reflection->FieldSize(*message, field)) {
Vitaly Buka4782c142017-03-04 08:12:32313 ConstFieldInstance source(message, field,
314 GetRandomIndex(random_, field_size));
Vitaly Bukaaf8136f2017-06-09 23:40:12315 if (match_.EnforceUtf8() && !source.EnforceUtf8()) continue;
Vitaly Buka4782c142017-03-04 08:12:32316 if (!IsEqualValueField()(match_, source))
317 sampler_.Try(field_size, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56318 }
319 } else {
320 if (reflection->HasField(*message, field)) {
Vitaly Buka4782c142017-03-04 08:12:32321 ConstFieldInstance source(message, field);
Vitaly Bukaaf8136f2017-06-09 23:40:12322 if (match_.EnforceUtf8() && !source.EnforceUtf8()) continue;
Vitaly Buka4782c142017-03-04 08:12:32323 if (!IsEqualValueField()(match_, source)) sampler_.Try(1, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56324 }
325 }
326 }
327 }
328
Vitaly Buka88712862017-02-27 06:21:30329 ConstFieldInstance match_;
Vitaly Bukaf62fe472017-03-02 07:05:15330 RandomEngine* random_;
Vitaly Bukaa3e59c72016-12-07 00:53:56331
Vitaly Bukaf62fe472017-03-02 07:05:15332 WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56333};
334
Vitaly Buka0e17fd72016-11-18 18:02:46335} // namespace
336
Vitaly Buka5d013202017-02-25 00:50:11337class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09338 public:
Vitaly Buka0e9439f2017-03-16 00:51:57339 FieldMutator(size_t size_increase_hint, bool enforce_changes,
Vitaly Bukaaf8136f2017-06-09 23:40:12340 bool enforce_utf8_strings, Mutator* mutator)
Vitaly Buka0e9439f2017-03-16 00:51:57341 : size_increase_hint_(size_increase_hint),
342 enforce_changes_(enforce_changes),
Vitaly Bukaaf8136f2017-06-09 23:40:12343 enforce_utf8_strings_(enforce_utf8_strings),
Vitaly Buka0e9439f2017-03-16 00:51:57344 mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41345
Vitaly Buka796b1122017-03-03 22:42:02346 void Mutate(int32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14347 RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02348 }
Vitaly Buka91ad7b02016-12-12 23:41:41349
Vitaly Buka796b1122017-03-03 22:42:02350 void Mutate(int64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14351 RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02352 }
Vitaly Buka91ad7b02016-12-12 23:41:41353
354 void Mutate(uint32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14355 RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41356 }
357
358 void Mutate(uint64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14359 RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41360 }
361
Vitaly Buka796b1122017-03-03 22:42:02362 void Mutate(float* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14363 RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02364 }
Vitaly Buka91ad7b02016-12-12 23:41:41365
Vitaly Buka796b1122017-03-03 22:42:02366 void Mutate(double* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14367 RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02368 }
Vitaly Buka91ad7b02016-12-12 23:41:41369
Vitaly Buka796b1122017-03-03 22:42:02370 void Mutate(bool* value) const {
Vitaly Buka0e9439f2017-03-16 00:51:57371 RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1), 2);
Vitaly Buka796b1122017-03-03 22:42:02372 }
Vitaly Buka91ad7b02016-12-12 23:41:41373
374 void Mutate(FieldInstance::Enum* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14375 RepeatMutate(&value->index,
Vitaly Buka0e9439f2017-03-16 00:51:57376 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count),
377 std::max<size_t>(value->count, 1));
Vitaly Buka91ad7b02016-12-12 23:41:41378 assert(value->index < value->count);
379 }
380
381 void Mutate(std::string* value) const {
Vitaly Bukaaf8136f2017-06-09 23:40:12382 if (enforce_utf8_strings_) {
383 RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1,
384 size_increase_hint_));
385 } else {
386 RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
387 size_increase_hint_));
388 }
Vitaly Buka91ad7b02016-12-12 23:41:41389 }
390
Vitaly Bukab2c4fb52017-03-16 18:50:40391 void Mutate(std::unique_ptr<Message>* message) const {
392 assert(!enforce_changes_);
393 assert(*message);
394 if (GetRandomBool(mutator_->random(), 100)) return;
395 mutator_->Mutate(message->get(), size_increase_hint_);
396 }
Vitaly Buka432b5452016-12-09 22:42:09397
Vitaly Buka5d013202017-02-25 00:50:11398 private:
Vitaly Buka796b1122017-03-03 22:42:02399 template <class T, class F>
Vitaly Buka0e9439f2017-03-16 00:51:57400 void RepeatMutate(T* value, F mutate,
401 size_t unchanged_one_out_of = 100) const {
402 if (!enforce_changes_ &&
Vitaly Bukab2c4fb52017-03-16 18:50:40403 GetRandomBool(mutator_->random(), unchanged_one_out_of)) {
Vitaly Buka0e9439f2017-03-16 00:51:57404 return;
Vitaly Bukab2c4fb52017-03-16 18:50:40405 }
Vitaly Buka796b1122017-03-03 22:42:02406 T tmp = *value;
407 for (int i = 0; i < 10; ++i) {
408 *value = mutate(*value);
Vitaly Buka0e9439f2017-03-16 00:51:57409 if (!enforce_changes_ || *value != tmp) return;
Vitaly Buka796b1122017-03-03 22:42:02410 }
411 }
412
Vitaly Buka5d013202017-02-25 00:50:11413 size_t size_increase_hint_;
Vitaly Buka0e9439f2017-03-16 00:51:57414 size_t enforce_changes_;
Vitaly Bukaaf8136f2017-06-09 23:40:12415 bool enforce_utf8_strings_;
Vitaly Bukae79e0182017-03-02 00:02:14416 Mutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09417};
418
Vitaly Buka5d013202017-02-25 00:50:11419namespace {
420
Vitaly Bukad4ab1e72017-03-04 07:51:19421struct MutateField : public FieldFunction<MutateField> {
Vitaly Buka5d013202017-02-25 00:50:11422 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19423 void ForType(const FieldInstance& field, size_t size_increase_hint,
Vitaly Bukae79e0182017-03-02 00:02:14424 Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11425 T value;
426 field.Load(&value);
Vitaly Bukaaf8136f2017-06-09 23:40:12427 FieldMutator(size_increase_hint, true, field.EnforceUtf8(), mutator)
428 .Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11429 field.Store(value);
430 }
Vitaly Buka5d013202017-02-25 00:50:11431};
432
Vitaly Bukad4ab1e72017-03-04 07:51:19433struct CreateField : public FieldFunction<CreateField> {
Vitaly Buka5d013202017-02-25 00:50:11434 public:
Vitaly Buka5d013202017-02-25 00:50:11435 template <class T>
Vitaly Buka490b23a2017-03-13 06:47:58436 void ForType(const FieldInstance& field, size_t size_increase_hint,
437 Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11438 T value;
439 field.GetDefault(&value);
Vitaly Buka0e9439f2017-03-16 00:51:57440 FieldMutator field_mutator(size_increase_hint,
Vitaly Bukaaf8136f2017-06-09 23:40:12441 false /* defaults could be useful */,
442 field.EnforceUtf8(), mutator);
Vitaly Buka0e9439f2017-03-16 00:51:57443 field_mutator.Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11444 field.Create(value);
445 }
Vitaly Buka5d013202017-02-25 00:50:11446};
447
448} // namespace
449
Vitaly Bukaf62fe472017-03-02 07:05:15450Mutator::Mutator(RandomEngine* random) : random_(random) {}
Vitaly Buka432b5452016-12-09 22:42:09451
Vitaly Bukae79e0182017-03-02 00:02:14452void Mutator::Mutate(Message* message, size_t size_increase_hint) {
Vitaly Buka66d06c72017-03-04 09:22:34453 bool repeat;
454 do {
455 repeat = false;
Vitaly Buka329fa462017-03-15 23:52:17456 MutationSampler mutation(keep_initialized_, random_, message);
Vitaly Buka66d06c72017-03-04 09:22:34457 switch (mutation.mutation()) {
458 case Mutation::None:
459 break;
460 case Mutation::Add:
Vitaly Buka0e9439f2017-03-16 00:51:57461 CreateField()(mutation.field(), size_increase_hint / 2, this);
Vitaly Buka66d06c72017-03-04 09:22:34462 break;
463 case Mutation::Mutate:
464 MutateField()(mutation.field(), size_increase_hint / 2, this);
465 break;
466 case Mutation::Delete:
Vitaly Bukad4ab1e72017-03-04 07:51:19467 DeleteField()(mutation.field());
Vitaly Bukaa3e59c72016-12-07 00:53:56468 break;
Vitaly Buka66d06c72017-03-04 09:22:34469 case Mutation::Copy: {
Vitaly Bukaf62fe472017-03-02 07:05:15470 DataSourceSampler source(mutation.field(), random_, message);
Vitaly Buka66d06c72017-03-04 09:22:34471 if (source.IsEmpty()) {
472 repeat = true;
473 break;
474 }
475 CopyField()(source.field(), mutation.field());
476 break;
Vitaly Bukaa3e59c72016-12-07 00:53:56477 }
Vitaly Buka66d06c72017-03-04 09:22:34478 default:
479 assert(false && "unexpected mutation");
Vitaly Bukaa3e59c72016-12-07 00:53:56480 }
Vitaly Buka66d06c72017-03-04 09:22:34481 } while (repeat);
Vitaly Buka0e17fd72016-11-18 18:02:46482
Vitaly Bukae4eae602017-09-29 00:28:12483 InitializeAndTrim(message, kMaxInitializeDepth);
484 assert(!keep_initialized_ || message->IsInitialized());
Vitaly Buka00b61072016-10-19 23:22:51485}
486
Vitaly Bukae79e0182017-03-02 00:02:14487void Mutator::CrossOver(const protobuf::Message& message1,
488 protobuf::Message* message2) {
Vitaly Buka142e08b2017-03-06 00:26:15489 // CrossOver can produce result which still equals to inputs. So we backup
490 // message2 to later comparison. message1 is already constant.
491 std::unique_ptr<protobuf::Message> message2_copy(message2->New());
492 message2_copy->CopyFrom(*message2);
493
Vitaly Bukaadfc27c2017-02-27 06:36:36494 CrossOverImpl(message1, message2);
495
Vitaly Bukae4eae602017-09-29 00:28:12496 InitializeAndTrim(message2, kMaxInitializeDepth);
497 assert(!keep_initialized_ || message2->IsInitialized());
Vitaly Buka142e08b2017-03-06 00:26:15498
Vitaly Buka2d609df2017-03-07 07:29:47499 // Can't call mutate from crossover because of a bug in libFuzzer.
500 return;
501 // if (MessageDifferencer::Equals(*message2_copy, *message2) ||
502 // MessageDifferencer::Equals(message1, *message2)) {
503 // Mutate(message2, 0);
504 // }
Vitaly Bukaadfc27c2017-02-27 06:36:36505}
506
Vitaly Bukae79e0182017-03-02 00:02:14507void Mutator::CrossOverImpl(const protobuf::Message& message1,
508 protobuf::Message* message2) {
Vitaly Bukaadfc27c2017-02-27 06:36:36509 const Descriptor* descriptor = message2->GetDescriptor();
510 const Reflection* reflection = message2->GetReflection();
511 assert(message1.GetDescriptor() == descriptor);
512 assert(message1.GetReflection() == reflection);
513
514 for (int i = 0; i < descriptor->field_count(); ++i) {
515 const FieldDescriptor* field = descriptor->field(i);
516
517 if (field->is_repeated()) {
518 const int field_size1 = reflection->FieldSize(message1, field);
519 int field_size2 = reflection->FieldSize(*message2, field);
520 for (int j = 0; j < field_size1; ++j) {
521 ConstFieldInstance source(&message1, field, j);
522 FieldInstance destination(message2, field, field_size2++);
Vitaly Bukad4ab1e72017-03-04 07:51:19523 AppendField()(source, destination);
Vitaly Bukaadfc27c2017-02-27 06:36:36524 }
525
526 assert(field_size2 == reflection->FieldSize(*message2, field));
527
528 // Shuffle
529 for (int j = 0; j < field_size2; ++j) {
Vitaly Bukaf62fe472017-03-02 07:05:15530 if (int k = GetRandomIndex(random_, field_size2 - j)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36531 reflection->SwapElements(message2, field, j, j + k);
532 }
533 }
534
Vitaly Bukaf62fe472017-03-02 07:05:15535 int keep = GetRandomIndex(random_, field_size2 + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36536
537 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
538 int remove = field_size2 - keep;
539 // Cross some message to keep with messages to remove.
Vitaly Bukaf62fe472017-03-02 07:05:15540 int cross = GetRandomIndex(random_, std::min(keep, remove) + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36541 for (int j = 0; j < cross; ++j) {
Vitaly Bukaf62fe472017-03-02 07:05:15542 int k = GetRandomIndex(random_, keep);
543 int r = keep + GetRandomIndex(random_, remove);
Vitaly Bukaadfc27c2017-02-27 06:36:36544 assert(k != r);
545 CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
546 reflection->MutableRepeatedMessage(message2, field, k));
547 }
548 }
549
550 for (int j = keep; j < field_size2; ++j)
551 reflection->RemoveLast(message2, field);
552 assert(keep == reflection->FieldSize(*message2, field));
553
554 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
555 if (!reflection->HasField(message1, field)) {
Vitaly Bukaf62fe472017-03-02 07:05:15556 if (GetRandomBool(random_))
Vitaly Bukad4ab1e72017-03-04 07:51:19557 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36558 } else if (!reflection->HasField(*message2, field)) {
Vitaly Bukaf62fe472017-03-02 07:05:15559 if (GetRandomBool(random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36560 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19561 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36562 }
563 } else {
564 CrossOverImpl(reflection->GetMessage(message1, field),
565 reflection->MutableMessage(message2, field));
566 }
567 } else {
Vitaly Bukaf62fe472017-03-02 07:05:15568 if (GetRandomBool(random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36569 if (reflection->HasField(message1, field)) {
570 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19571 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36572 } else {
Vitaly Bukad4ab1e72017-03-04 07:51:19573 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36574 }
575 }
576 }
577 }
578}
579
Vitaly Bukae4eae602017-09-29 00:28:12580void Mutator::InitializeAndTrim(Message* message, int max_depth) {
Vitaly Buka13245af2016-11-18 21:20:12581 const Descriptor* descriptor = message->GetDescriptor();
582 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12583 for (int i = 0; i < descriptor->field_count(); ++i) {
584 const FieldDescriptor* field = descriptor->field(i);
Vitaly Bukae4eae602017-09-29 00:28:12585 if (keep_initialized_ && field->is_required() &&
586 !reflection->HasField(*message, field))
Vitaly Bukad4ab1e72017-03-04 07:51:19587 CreateDefaultField()(FieldInstance(message, field));
Vitaly Buka13245af2016-11-18 21:20:12588
Vitaly Bukae4eae602017-09-29 00:28:12589 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
590 if (max_depth <= 0 && !field->is_required()) {
591 // Clear deep optional fields to avoid stack overflow.
592 reflection->ClearField(message, field);
593 if (field->is_repeated())
594 assert(!reflection->FieldSize(*message, field));
595 else
596 assert(!reflection->HasField(*message, field));
597 continue;
598 }
599
Vitaly Buka2cfe02b2016-11-19 00:34:09600 if (field->is_repeated()) {
601 const int field_size = reflection->FieldSize(*message, field);
602 for (int j = 0; j < field_size; ++j) {
603 Message* nested_message =
604 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Bukae4eae602017-09-29 00:28:12605 InitializeAndTrim(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09606 }
607 } else if (reflection->HasField(*message, field)) {
608 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Bukae4eae602017-09-29 00:28:12609 InitializeAndTrim(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12610 }
611 }
612 }
613}
Vitaly Buka4af611d2016-12-04 02:57:32614
Vitaly Bukaf62fe472017-03-02 07:05:15615int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, random_); }
Vitaly Bukae79e0182017-03-02 00:02:14616
Vitaly Bukaf62fe472017-03-02 07:05:15617int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, random_); }
Vitaly Bukae79e0182017-03-02 00:02:14618
619uint32_t Mutator::MutateUInt32(uint32_t value) {
Vitaly Bukaf62fe472017-03-02 07:05:15620 return FlipBit(value, random_);
Vitaly Buka4af611d2016-12-04 02:57:32621}
622
Vitaly Bukae79e0182017-03-02 00:02:14623uint64_t Mutator::MutateUInt64(uint64_t value) {
Vitaly Bukaf62fe472017-03-02 07:05:15624 return FlipBit(value, random_);
Vitaly Buka4af611d2016-12-04 02:57:32625}
626
Vitaly Bukaf62fe472017-03-02 07:05:15627float Mutator::MutateFloat(float value) { return FlipBit(value, random_); }
Vitaly Buka4af611d2016-12-04 02:57:32628
Vitaly Bukaf62fe472017-03-02 07:05:15629double Mutator::MutateDouble(double value) { return FlipBit(value, random_); }
Vitaly Buka4af611d2016-12-04 02:57:32630
Vitaly Bukae79e0182017-03-02 00:02:14631bool Mutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-04 02:57:32632
Vitaly Bukae79e0182017-03-02 00:02:14633size_t Mutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukaee1c76a2017-03-15 17:48:53634 if (item_count <= 1) return 0;
Vitaly Bukaf62fe472017-03-02 07:05:15635 return (index + 1 + GetRandomIndex(random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-04 02:57:32636}
637
Vitaly Bukae79e0182017-03-02 00:02:14638std::string Mutator::MutateString(const std::string& value,
639 size_t size_increase_hint) {
Vitaly Buka4af611d2016-12-04 02:57:32640 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11641
Vitaly Bukaf62fe472017-03-02 07:05:15642 while (!result.empty() && GetRandomBool(random_)) {
643 result.erase(GetRandomIndex(random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09644 }
645
Vitaly Bukaf62fe472017-03-02 07:05:15646 while (result.size() < size_increase_hint && GetRandomBool(random_)) {
647 size_t index = GetRandomIndex(random_, result.size() + 1);
648 result.insert(result.begin() + index, GetRandomIndex(random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09649 }
650
Vitaly Bukac020de12017-03-04 03:36:23651 if (result != value) return result;
652
653 if (result.empty()) {
Vitaly Bukaf62fe472017-03-02 07:05:15654 result.push_back(GetRandomIndex(random_, 1 << 8));
Vitaly Bukac020de12017-03-04 03:36:23655 return result;
656 }
657
Vitaly Buka4af611d2016-12-04 02:57:32658 if (!result.empty())
Vitaly Bukaf62fe472017-03-02 07:05:15659 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), random_);
Vitaly Buka4af611d2016-12-04 02:57:32660 return result;
661}
Vitaly Buka432b5452016-12-09 22:42:09662
Vitaly Bukaaf8136f2017-06-09 23:40:12663std::string Mutator::MutateUtf8String(const std::string& value,
664 size_t size_increase_hint) {
665 std::string str = MutateString(value, size_increase_hint);
666 FixUtf8String(&str, random_);
667 return str;
668}
669
Vitaly Buka432b5452016-12-09 22:42:09670} // namespace protobuf_mutator