blob: 7dc8f44f3bfdafb1eb731ea5f5a1825b083a369d [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>
Vitaly Buka00b61072016-10-19 23:22:5121
Vitaly Buka9dd2f8e2017-01-13 08:48:3122#include "src/field_instance.h"
Vitaly Bukaaf8136f2017-06-09 23:40:1223#include "src/utf8_fix.h"
Vitaly Buka9dd2f8e2017-01-13 08:48:3124#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 23:22:5125
Vitaly Bukaf86815c2017-02-27 22:19:1926namespace protobuf_mutator {
27
Vitaly Buka6c6dbbe2017-02-22 21:58:2428using protobuf::Descriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2429using protobuf::FieldDescriptor;
Vitaly Buka796b1122017-03-03 22:42:0230using protobuf::FileDescriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2431using protobuf::Message;
32using protobuf::OneofDescriptor;
33using protobuf::Reflection;
Vitaly Buka4782c142017-03-04 08:12:3234using protobuf::util::MessageDifferencer;
Vitaly Buka796b1122017-03-03 22:42:0235using std::placeholders::_1;
Vitaly Buka0e17fd72016-11-18 18:02:4636
37namespace {
38
Vitaly Buka72019dc2016-12-15 03:17:2439const size_t kMaxInitializeDepth = 32;
Vitaly Buka329fa462017-03-15 23:52:1740const uint64_t kDefaultMutateWeight = 1000000;
Vitaly Buka0e17fd72016-11-18 18:02:4641
42enum class Mutation {
Vitaly Buka30de3092016-11-18 19:39:0743 None,
Vitaly Buka4af611d2016-12-04 02:57:3244 Add, // Adds new field with default value.
45 Mutate, // Mutates field contents.
46 Delete, // Deletes field.
Vitaly Bukaa3e59c72016-12-07 00:53:5647 Copy, // Copy values copied from another field.
Vitaly Buka4af611d2016-12-04 02:57:3248
Vitaly Buka432b5452016-12-09 22:42:0949 // TODO(vitalybuka):
50 // Clone, // Adds new field with value copied from another field.
Vitaly Buka0e17fd72016-11-18 18:02:4651};
52
Vitaly Bukab592ff02017-03-03 22:35:5253// Return random integer from [0, count)
Vitaly Bukaf62fe472017-03-02 07:05:1554size_t GetRandomIndex(RandomEngine* random, size_t count) {
Vitaly Bukab592ff02017-03-03 22:35:5255 assert(count > 0);
56 if (count == 1) return 0;
57 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
58}
59
Vitaly Buka4af611d2016-12-04 02:57:3260// Flips random bit in the buffer.
Vitaly Bukaf62fe472017-03-02 07:05:1561void FlipBit(size_t size, uint8_t* bytes, RandomEngine* random) {
Vitaly Bukab592ff02017-03-03 22:35:5262 size_t bit = GetRandomIndex(random, size * 8);
Vitaly Buka4af611d2016-12-04 02:57:3263 bytes[bit / 8] ^= (1u << (bit % 8));
64}
Vitaly Buka781853c2016-11-22 07:09:3565
Vitaly Buka4af611d2016-12-04 02:57:3266// Flips random bit in the value.
67template <class T>
Vitaly Bukaf62fe472017-03-02 07:05:1568T FlipBit(T value, RandomEngine* random) {
Vitaly Buka4af611d2016-12-04 02:57:3269 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
70 return value;
71}
Vitaly Buka781853c2016-11-22 07:09:3572
Vitaly Bukabeb90802017-02-28 23:28:1073// Return true with probability about 1-of-n.
Vitaly Bukaf62fe472017-03-02 07:05:1574bool GetRandomBool(RandomEngine* random, size_t n = 2) {
Vitaly Bukabeb90802017-02-28 23:28:1075 return GetRandomIndex(random, n) == 0;
76}
77
Vitaly Buka28ca0ee2017-03-05 05:35:4278bool IsProto3SimpleField(const FieldDescriptor& field) {
79 assert(field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
80 field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2);
81 return field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
82 field.cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
83 !field.containing_oneof() && !field.is_repeated();
84}
85
Vitaly Bukad4ab1e72017-03-04 07:51:1986struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
Vitaly Buka91ad7b02016-12-12 23:41:4187 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:1988 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:4189 T value;
90 field.GetDefault(&value);
91 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:3292 }
Vitaly Buka91ad7b02016-12-12 23:41:4193};
Vitaly Bukabec52222016-12-09 22:29:3294
Vitaly Bukad4ab1e72017-03-04 07:51:1995struct DeleteField : public FieldFunction<DeleteField> {
Vitaly Buka91ad7b02016-12-12 23:41:4196 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:1997 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:4198 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:3299 }
Vitaly Bukabec52222016-12-09 22:29:32100};
101
Vitaly Bukad4ab1e72017-03-04 07:51:19102struct CopyField : public FieldFunction<CopyField> {
Vitaly Bukaa3e59c72016-12-07 00:53:56103 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19104 void ForType(const ConstFieldInstance& source,
105 const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:56106 T value;
107 source.Load(&value);
108 field.Store(value);
109 }
Vitaly Bukaa3e59c72016-12-07 00:53:56110};
111
Vitaly Bukad4ab1e72017-03-04 07:51:19112struct AppendField : public FieldFunction<AppendField> {
Vitaly Bukaadfc27c2017-02-27 06:36:36113 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19114 void ForType(const ConstFieldInstance& source,
115 const FieldInstance& field) const {
Vitaly Bukaadfc27c2017-02-27 06:36:36116 T value;
117 source.Load(&value);
118 field.Create(value);
119 }
Vitaly Bukaadfc27c2017-02-27 06:36:36120};
121
Vitaly Buka4782c142017-03-04 08:12:32122class IsEqualValueField : public FieldFunction<IsEqualValueField, bool> {
123 public:
124 template <class T>
125 bool ForType(const ConstFieldInstance& a, const ConstFieldInstance& b) const {
126 T aa;
127 a.Load(&aa);
128 T bb;
129 b.Load(&bb);
130 return IsEqual(aa, bb);
131 }
132
133 private:
134 bool IsEqual(const ConstFieldInstance::Enum& a,
135 const ConstFieldInstance::Enum& b) const {
136 assert(a.count == b.count);
137 return a.index == b.index;
138 }
139
140 bool IsEqual(const std::unique_ptr<protobuf::Message>& a,
141 const std::unique_ptr<protobuf::Message>& b) const {
142 return MessageDifferencer::Equals(*a, *b);
143 }
144
145 template <class T>
146 bool IsEqual(const T& a, const T& b) const {
147 return a == b;
148 }
149};
150
Vitaly Buka4af611d2016-12-04 02:57:32151// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35152class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17153 public:
Vitaly Buka329fa462017-03-15 23:52:17154 MutationSampler(bool keep_initialized, RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-04 02:57:32155 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka781853c2016-11-22 07:09:35156 Sample(message);
Vitaly Bukaf3383a92017-03-20 00:04:18157 assert(mutation() != Mutation::None ||
158 message->GetDescriptor()->field_count() == 0);
Vitaly Bukac9d22482016-11-21 21:29:17159 }
160
Vitaly Buka4af611d2016-12-04 02:57:32161 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32162 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32163
164 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09165 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32166
167 private:
Vitaly Buka781853c2016-11-22 07:09:35168 void Sample(Message* message) {
169 const Descriptor* descriptor = message->GetDescriptor();
170 const Reflection* reflection = message->GetReflection();
171
172 int field_count = descriptor->field_count();
173 for (int i = 0; i < field_count; ++i) {
174 const FieldDescriptor* field = descriptor->field(i);
175 if (const OneofDescriptor* oneof = field->containing_oneof()) {
176 // Handle entire oneof group on the first field.
177 if (field->index_in_oneof() == 0) {
Vitaly Buka2f660a52017-03-04 03:46:14178 assert(oneof->field_count());
179 const FieldDescriptor* current_field =
180 reflection->GetOneofFieldDescriptor(*message, oneof);
181 for (;;) {
182 const FieldDescriptor* add_field =
183 oneof->field(GetRandomIndex(random_, oneof->field_count()));
184 if (add_field != current_field) {
Vitaly Buka329fa462017-03-15 23:52:17185 sampler_.Try(kDefaultMutateWeight,
186 {{message, add_field}, Mutation::Add});
Vitaly Buka2f660a52017-03-04 03:46:14187 break;
188 }
189 if (oneof->field_count() < 2) break;
190 }
191 if (current_field) {
Vitaly Buka28ca0ee2017-03-05 05:35:42192 if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka329fa462017-03-15 23:52:17193 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14194 {{message, current_field}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42195 }
Vitaly Buka329fa462017-03-15 23:52:17196 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14197 {{message, current_field}, Mutation::Delete});
Vitaly Buka329fa462017-03-15 23:52:17198 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14199 {{message, current_field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35200 }
201 }
202 } else {
203 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32204 int field_size = reflection->FieldSize(*message, field);
Vitaly Buka329fa462017-03-15 23:52:17205 sampler_.Try(
206 kDefaultMutateWeight,
207 {{message, field, GetRandomIndex(random_, field_size + 1)},
208 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35209
Vitaly Bukabec52222016-12-09 22:29:32210 if (field_size) {
211 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka28ca0ee2017-03-05 05:35:42212 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka329fa462017-03-15 23:52:17213 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32214 {{message, field, random_index}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42215 }
Vitaly Buka329fa462017-03-15 23:52:17216 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32217 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka329fa462017-03-15 23:52:17218 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukaa3e59c72016-12-07 00:53:56219 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35220 }
221 } else {
Vitaly Buka28ca0ee2017-03-05 05:35:42222 if (reflection->HasField(*message, field) ||
223 IsProto3SimpleField(*field)) {
Vitaly Buka4af611d2016-12-04 02:57:32224 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Buka329fa462017-03-15 23:52:17225 sampler_.Try(kDefaultMutateWeight,
226 {{message, field}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42227 if (!IsProto3SimpleField(*field) &&
228 (!field->is_required() || !keep_initialized_)) {
Vitaly Buka329fa462017-03-15 23:52:17229 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32230 {{message, field}, Mutation::Delete});
Vitaly Buka28ca0ee2017-03-05 05:35:42231 }
Vitaly Buka329fa462017-03-15 23:52:17232 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka72019dc2016-12-15 03:17:24233 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35234 } else {
Vitaly Buka329fa462017-03-15 23:52:17235 sampler_.Try(kDefaultMutateWeight,
236 {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35237 }
238 }
239 }
240
241 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
242 if (field->is_repeated()) {
243 const int field_size = reflection->FieldSize(*message, field);
244 for (int j = 0; j < field_size; ++j)
245 Sample(reflection->MutableRepeatedMessage(message, field, j));
246 } else if (reflection->HasField(*message, field)) {
247 Sample(reflection->MutableMessage(message, field));
248 }
249 }
250 }
251 }
252
Vitaly Buka781853c2016-11-22 07:09:35253 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32254
Vitaly Bukaf62fe472017-03-02 07:05:15255 RandomEngine* random_;
Vitaly Buka4af611d2016-12-04 02:57:32256
257 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41258 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32259 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41260
Vitaly Bukabec52222016-12-09 22:29:32261 FieldInstance field;
262 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32263 };
Vitaly Bukaf62fe472017-03-02 07:05:15264 WeightedReservoirSampler<Result, RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17265};
266
Vitaly Bukaa3e59c72016-12-07 00:53:56267// Selects random field of compatible type to use for clone mutations.
268class DataSourceSampler {
269 public:
Vitaly Bukaf62fe472017-03-02 07:05:15270 DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
271 Message* message)
Vitaly Bukaa3e59c72016-12-07 00:53:56272 : match_(match), random_(random), sampler_(random) {
273 Sample(message);
274 }
275
276 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30277 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24278 assert(!IsEmpty());
279 return sampler_.selected();
280 }
281
282 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56283
284 private:
285 void Sample(Message* message) {
286 const Descriptor* descriptor = message->GetDescriptor();
287 const Reflection* reflection = message->GetReflection();
288
289 int field_count = descriptor->field_count();
290 for (int i = 0; i < field_count; ++i) {
291 const FieldDescriptor* field = descriptor->field(i);
292 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
293 if (field->is_repeated()) {
294 const int field_size = reflection->FieldSize(*message, field);
295 for (int j = 0; j < field_size; ++j) {
296 Sample(reflection->MutableRepeatedMessage(message, field, j));
297 }
298 } else if (reflection->HasField(*message, field)) {
299 Sample(reflection->MutableMessage(message, field));
300 }
301 }
302
303 if (field->cpp_type() != match_.cpp_type()) continue;
304 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
305 if (field->enum_type() != match_.enum_type()) continue;
306 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
307 if (field->message_type() != match_.message_type()) continue;
308 }
309
Vitaly Bukaa3e59c72016-12-07 00:53:56310 if (field->is_repeated()) {
311 if (int field_size = reflection->FieldSize(*message, field)) {
Vitaly Buka4782c142017-03-04 08:12:32312 ConstFieldInstance source(message, field,
313 GetRandomIndex(random_, field_size));
Vitaly Bukaaf8136f2017-06-09 23:40:12314 if (match_.EnforceUtf8() && !source.EnforceUtf8()) continue;
Vitaly Buka4782c142017-03-04 08:12:32315 if (!IsEqualValueField()(match_, source))
316 sampler_.Try(field_size, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56317 }
318 } else {
319 if (reflection->HasField(*message, field)) {
Vitaly Buka4782c142017-03-04 08:12:32320 ConstFieldInstance source(message, field);
Vitaly Bukaaf8136f2017-06-09 23:40:12321 if (match_.EnforceUtf8() && !source.EnforceUtf8()) continue;
Vitaly Buka4782c142017-03-04 08:12:32322 if (!IsEqualValueField()(match_, source)) sampler_.Try(1, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56323 }
324 }
325 }
326 }
327
Vitaly Buka88712862017-02-27 06:21:30328 ConstFieldInstance match_;
Vitaly Bukaf62fe472017-03-02 07:05:15329 RandomEngine* random_;
Vitaly Bukaa3e59c72016-12-07 00:53:56330
Vitaly Bukaf62fe472017-03-02 07:05:15331 WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56332};
333
Vitaly Buka0e17fd72016-11-18 18:02:46334} // namespace
335
Vitaly Buka5d013202017-02-25 00:50:11336class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09337 public:
Vitaly Buka0e9439f2017-03-16 00:51:57338 FieldMutator(size_t size_increase_hint, bool enforce_changes,
Vitaly Bukaaf8136f2017-06-09 23:40:12339 bool enforce_utf8_strings, Mutator* mutator)
Vitaly Buka0e9439f2017-03-16 00:51:57340 : size_increase_hint_(size_increase_hint),
341 enforce_changes_(enforce_changes),
Vitaly Bukaaf8136f2017-06-09 23:40:12342 enforce_utf8_strings_(enforce_utf8_strings),
Vitaly Buka0e9439f2017-03-16 00:51:57343 mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41344
Vitaly Buka796b1122017-03-03 22:42:02345 void Mutate(int32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14346 RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02347 }
Vitaly Buka91ad7b02016-12-12 23:41:41348
Vitaly Buka796b1122017-03-03 22:42:02349 void Mutate(int64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14350 RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02351 }
Vitaly Buka91ad7b02016-12-12 23:41:41352
353 void Mutate(uint32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14354 RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41355 }
356
357 void Mutate(uint64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14358 RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41359 }
360
Vitaly Buka796b1122017-03-03 22:42:02361 void Mutate(float* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14362 RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02363 }
Vitaly Buka91ad7b02016-12-12 23:41:41364
Vitaly Buka796b1122017-03-03 22:42:02365 void Mutate(double* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14366 RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02367 }
Vitaly Buka91ad7b02016-12-12 23:41:41368
Vitaly Buka796b1122017-03-03 22:42:02369 void Mutate(bool* value) const {
Vitaly Buka0e9439f2017-03-16 00:51:57370 RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1), 2);
Vitaly Buka796b1122017-03-03 22:42:02371 }
Vitaly Buka91ad7b02016-12-12 23:41:41372
373 void Mutate(FieldInstance::Enum* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14374 RepeatMutate(&value->index,
Vitaly Buka0e9439f2017-03-16 00:51:57375 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count),
376 std::max<size_t>(value->count, 1));
Vitaly Buka91ad7b02016-12-12 23:41:41377 assert(value->index < value->count);
378 }
379
380 void Mutate(std::string* value) const {
Vitaly Bukaaf8136f2017-06-09 23:40:12381 if (enforce_utf8_strings_) {
382 RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1,
383 size_increase_hint_));
384 } else {
385 RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
386 size_increase_hint_));
387 }
Vitaly Buka91ad7b02016-12-12 23:41:41388 }
389
Vitaly Bukab2c4fb52017-03-16 18:50:40390 void Mutate(std::unique_ptr<Message>* message) const {
391 assert(!enforce_changes_);
392 assert(*message);
393 if (GetRandomBool(mutator_->random(), 100)) return;
394 mutator_->Mutate(message->get(), size_increase_hint_);
395 }
Vitaly Buka432b5452016-12-09 22:42:09396
Vitaly Buka5d013202017-02-25 00:50:11397 private:
Vitaly Buka796b1122017-03-03 22:42:02398 template <class T, class F>
Vitaly Buka0e9439f2017-03-16 00:51:57399 void RepeatMutate(T* value, F mutate,
400 size_t unchanged_one_out_of = 100) const {
401 if (!enforce_changes_ &&
Vitaly Bukab2c4fb52017-03-16 18:50:40402 GetRandomBool(mutator_->random(), unchanged_one_out_of)) {
Vitaly Buka0e9439f2017-03-16 00:51:57403 return;
Vitaly Bukab2c4fb52017-03-16 18:50:40404 }
Vitaly Buka796b1122017-03-03 22:42:02405 T tmp = *value;
406 for (int i = 0; i < 10; ++i) {
407 *value = mutate(*value);
Vitaly Buka0e9439f2017-03-16 00:51:57408 if (!enforce_changes_ || *value != tmp) return;
Vitaly Buka796b1122017-03-03 22:42:02409 }
410 }
411
Vitaly Buka5d013202017-02-25 00:50:11412 size_t size_increase_hint_;
Vitaly Buka0e9439f2017-03-16 00:51:57413 size_t enforce_changes_;
Vitaly Bukaaf8136f2017-06-09 23:40:12414 bool enforce_utf8_strings_;
Vitaly Bukae79e0182017-03-02 00:02:14415 Mutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09416};
417
Vitaly Buka5d013202017-02-25 00:50:11418namespace {
419
Vitaly Bukad4ab1e72017-03-04 07:51:19420struct MutateField : public FieldFunction<MutateField> {
Vitaly Buka5d013202017-02-25 00:50:11421 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19422 void ForType(const FieldInstance& field, size_t size_increase_hint,
Vitaly Bukae79e0182017-03-02 00:02:14423 Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11424 T value;
425 field.Load(&value);
Vitaly Bukaaf8136f2017-06-09 23:40:12426 FieldMutator(size_increase_hint, true, field.EnforceUtf8(), mutator)
427 .Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11428 field.Store(value);
429 }
Vitaly Buka5d013202017-02-25 00:50:11430};
431
Vitaly Bukad4ab1e72017-03-04 07:51:19432struct CreateField : public FieldFunction<CreateField> {
Vitaly Buka5d013202017-02-25 00:50:11433 public:
Vitaly Buka5d013202017-02-25 00:50:11434 template <class T>
Vitaly Buka490b23a2017-03-13 06:47:58435 void ForType(const FieldInstance& field, size_t size_increase_hint,
436 Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11437 T value;
438 field.GetDefault(&value);
Vitaly Buka0e9439f2017-03-16 00:51:57439 FieldMutator field_mutator(size_increase_hint,
Vitaly Bukaaf8136f2017-06-09 23:40:12440 false /* defaults could be useful */,
441 field.EnforceUtf8(), mutator);
Vitaly Buka0e9439f2017-03-16 00:51:57442 field_mutator.Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11443 field.Create(value);
444 }
Vitaly Buka5d013202017-02-25 00:50:11445};
446
447} // namespace
448
Vitaly Bukaf62fe472017-03-02 07:05:15449Mutator::Mutator(RandomEngine* random) : random_(random) {}
Vitaly Buka432b5452016-12-09 22:42:09450
Vitaly Bukae79e0182017-03-02 00:02:14451void Mutator::Mutate(Message* message, size_t size_increase_hint) {
Vitaly Buka66d06c72017-03-04 09:22:34452 bool repeat;
453 do {
454 repeat = false;
Vitaly Buka329fa462017-03-15 23:52:17455 MutationSampler mutation(keep_initialized_, random_, message);
Vitaly Buka66d06c72017-03-04 09:22:34456 switch (mutation.mutation()) {
457 case Mutation::None:
458 break;
459 case Mutation::Add:
Vitaly Buka0e9439f2017-03-16 00:51:57460 CreateField()(mutation.field(), size_increase_hint / 2, this);
Vitaly Buka66d06c72017-03-04 09:22:34461 break;
462 case Mutation::Mutate:
463 MutateField()(mutation.field(), size_increase_hint / 2, this);
464 break;
465 case Mutation::Delete:
Vitaly Bukad4ab1e72017-03-04 07:51:19466 DeleteField()(mutation.field());
Vitaly Bukaa3e59c72016-12-07 00:53:56467 break;
Vitaly Buka66d06c72017-03-04 09:22:34468 case Mutation::Copy: {
Vitaly Bukaf62fe472017-03-02 07:05:15469 DataSourceSampler source(mutation.field(), random_, message);
Vitaly Buka66d06c72017-03-04 09:22:34470 if (source.IsEmpty()) {
471 repeat = true;
472 break;
473 }
474 CopyField()(source.field(), mutation.field());
475 break;
Vitaly Bukaa3e59c72016-12-07 00:53:56476 }
Vitaly Buka66d06c72017-03-04 09:22:34477 default:
478 assert(false && "unexpected mutation");
Vitaly Bukaa3e59c72016-12-07 00:53:56479 }
Vitaly Buka66d06c72017-03-04 09:22:34480 } while (repeat);
Vitaly Buka0e17fd72016-11-18 18:02:46481
Vitaly Buka781853c2016-11-22 07:09:35482 if (keep_initialized_ && !message->IsInitialized()) {
483 InitializeMessage(message, kMaxInitializeDepth);
484 assert(message->IsInitialized());
Vitaly Buka0e17fd72016-11-18 18:02:46485 }
Vitaly Buka00b61072016-10-19 23:22:51486}
487
Vitaly Bukae79e0182017-03-02 00:02:14488void Mutator::CrossOver(const protobuf::Message& message1,
489 protobuf::Message* message2) {
Vitaly Buka142e08b2017-03-06 00:26:15490 // CrossOver can produce result which still equals to inputs. So we backup
491 // message2 to later comparison. message1 is already constant.
492 std::unique_ptr<protobuf::Message> message2_copy(message2->New());
493 message2_copy->CopyFrom(*message2);
494
Vitaly Bukaadfc27c2017-02-27 06:36:36495 CrossOverImpl(message1, message2);
496
497 if (keep_initialized_ && !message2->IsInitialized()) {
498 InitializeMessage(message2, kMaxInitializeDepth);
499 assert(message2->IsInitialized());
500 }
Vitaly Buka142e08b2017-03-06 00:26:15501
Vitaly Buka2d609df2017-03-07 07:29:47502 // Can't call mutate from crossover because of a bug in libFuzzer.
503 return;
504 // if (MessageDifferencer::Equals(*message2_copy, *message2) ||
505 // MessageDifferencer::Equals(message1, *message2)) {
506 // Mutate(message2, 0);
507 // }
Vitaly Bukaadfc27c2017-02-27 06:36:36508}
509
Vitaly Bukae79e0182017-03-02 00:02:14510void Mutator::CrossOverImpl(const protobuf::Message& message1,
511 protobuf::Message* message2) {
Vitaly Bukaadfc27c2017-02-27 06:36:36512 const Descriptor* descriptor = message2->GetDescriptor();
513 const Reflection* reflection = message2->GetReflection();
514 assert(message1.GetDescriptor() == descriptor);
515 assert(message1.GetReflection() == reflection);
516
517 for (int i = 0; i < descriptor->field_count(); ++i) {
518 const FieldDescriptor* field = descriptor->field(i);
519
520 if (field->is_repeated()) {
521 const int field_size1 = reflection->FieldSize(message1, field);
522 int field_size2 = reflection->FieldSize(*message2, field);
523 for (int j = 0; j < field_size1; ++j) {
524 ConstFieldInstance source(&message1, field, j);
525 FieldInstance destination(message2, field, field_size2++);
Vitaly Bukad4ab1e72017-03-04 07:51:19526 AppendField()(source, destination);
Vitaly Bukaadfc27c2017-02-27 06:36:36527 }
528
529 assert(field_size2 == reflection->FieldSize(*message2, field));
530
531 // Shuffle
532 for (int j = 0; j < field_size2; ++j) {
Vitaly Bukaf62fe472017-03-02 07:05:15533 if (int k = GetRandomIndex(random_, field_size2 - j)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36534 reflection->SwapElements(message2, field, j, j + k);
535 }
536 }
537
Vitaly Bukaf62fe472017-03-02 07:05:15538 int keep = GetRandomIndex(random_, field_size2 + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36539
540 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
541 int remove = field_size2 - keep;
542 // Cross some message to keep with messages to remove.
Vitaly Bukaf62fe472017-03-02 07:05:15543 int cross = GetRandomIndex(random_, std::min(keep, remove) + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36544 for (int j = 0; j < cross; ++j) {
Vitaly Bukaf62fe472017-03-02 07:05:15545 int k = GetRandomIndex(random_, keep);
546 int r = keep + GetRandomIndex(random_, remove);
Vitaly Bukaadfc27c2017-02-27 06:36:36547 assert(k != r);
548 CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
549 reflection->MutableRepeatedMessage(message2, field, k));
550 }
551 }
552
553 for (int j = keep; j < field_size2; ++j)
554 reflection->RemoveLast(message2, field);
555 assert(keep == reflection->FieldSize(*message2, field));
556
557 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
558 if (!reflection->HasField(message1, field)) {
Vitaly Bukaf62fe472017-03-02 07:05:15559 if (GetRandomBool(random_))
Vitaly Bukad4ab1e72017-03-04 07:51:19560 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36561 } else if (!reflection->HasField(*message2, field)) {
Vitaly Bukaf62fe472017-03-02 07:05:15562 if (GetRandomBool(random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36563 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19564 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36565 }
566 } else {
567 CrossOverImpl(reflection->GetMessage(message1, field),
568 reflection->MutableMessage(message2, field));
569 }
570 } else {
Vitaly Bukaf62fe472017-03-02 07:05:15571 if (GetRandomBool(random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36572 if (reflection->HasField(message1, field)) {
573 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19574 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36575 } else {
Vitaly Bukad4ab1e72017-03-04 07:51:19576 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36577 }
578 }
579 }
580 }
581}
582
Vitaly Bukae79e0182017-03-02 00:02:14583void Mutator::InitializeMessage(Message* message, size_t max_depth) {
Vitaly Buka781853c2016-11-22 07:09:35584 assert(keep_initialized_);
Vitaly Buka432b5452016-12-09 22:42:09585 // It's pointless but possible to have infinite recursion of required
586 // messages.
587 assert(max_depth);
Vitaly Buka13245af2016-11-18 21:20:12588 const Descriptor* descriptor = message->GetDescriptor();
589 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12590 for (int i = 0; i < descriptor->field_count(); ++i) {
591 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka91ad7b02016-12-12 23:41:41592 if (field->is_required() && !reflection->HasField(*message, field))
Vitaly Bukad4ab1e72017-03-04 07:51:19593 CreateDefaultField()(FieldInstance(message, field));
Vitaly Buka13245af2016-11-18 21:20:12594
Vitaly Buka781853c2016-11-22 07:09:35595 if (max_depth > 0 &&
596 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka2cfe02b2016-11-19 00:34:09597 if (field->is_repeated()) {
598 const int field_size = reflection->FieldSize(*message, field);
599 for (int j = 0; j < field_size; ++j) {
600 Message* nested_message =
601 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Buka781853c2016-11-22 07:09:35602 if (!nested_message->IsInitialized())
603 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09604 }
605 } else if (reflection->HasField(*message, field)) {
606 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Buka781853c2016-11-22 07:09:35607 if (!nested_message->IsInitialized())
608 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12609 }
610 }
611 }
612}
Vitaly Buka4af611d2016-12-04 02:57:32613
Vitaly Bukaf62fe472017-03-02 07:05:15614int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, random_); }
Vitaly Bukae79e0182017-03-02 00:02:14615
Vitaly Bukaf62fe472017-03-02 07:05:15616int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, random_); }
Vitaly Bukae79e0182017-03-02 00:02:14617
618uint32_t Mutator::MutateUInt32(uint32_t value) {
Vitaly Bukaf62fe472017-03-02 07:05:15619 return FlipBit(value, random_);
Vitaly Buka4af611d2016-12-04 02:57:32620}
621
Vitaly Bukae79e0182017-03-02 00:02:14622uint64_t Mutator::MutateUInt64(uint64_t value) {
Vitaly Bukaf62fe472017-03-02 07:05:15623 return FlipBit(value, random_);
Vitaly Buka4af611d2016-12-04 02:57:32624}
625
Vitaly Bukaf62fe472017-03-02 07:05:15626float Mutator::MutateFloat(float value) { return FlipBit(value, random_); }
Vitaly Buka4af611d2016-12-04 02:57:32627
Vitaly Bukaf62fe472017-03-02 07:05:15628double Mutator::MutateDouble(double value) { return FlipBit(value, random_); }
Vitaly Buka4af611d2016-12-04 02:57:32629
Vitaly Bukae79e0182017-03-02 00:02:14630bool Mutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-04 02:57:32631
Vitaly Bukae79e0182017-03-02 00:02:14632size_t Mutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukaee1c76a2017-03-15 17:48:53633 if (item_count <= 1) return 0;
Vitaly Bukaf62fe472017-03-02 07:05:15634 return (index + 1 + GetRandomIndex(random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-04 02:57:32635}
636
Vitaly Bukae79e0182017-03-02 00:02:14637std::string Mutator::MutateString(const std::string& value,
638 size_t size_increase_hint) {
Vitaly Buka4af611d2016-12-04 02:57:32639 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11640
Vitaly Bukaf62fe472017-03-02 07:05:15641 while (!result.empty() && GetRandomBool(random_)) {
642 result.erase(GetRandomIndex(random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09643 }
644
Vitaly Bukaf62fe472017-03-02 07:05:15645 while (result.size() < size_increase_hint && GetRandomBool(random_)) {
646 size_t index = GetRandomIndex(random_, result.size() + 1);
647 result.insert(result.begin() + index, GetRandomIndex(random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09648 }
649
Vitaly Bukac020de12017-03-04 03:36:23650 if (result != value) return result;
651
652 if (result.empty()) {
Vitaly Bukaf62fe472017-03-02 07:05:15653 result.push_back(GetRandomIndex(random_, 1 << 8));
Vitaly Bukac020de12017-03-04 03:36:23654 return result;
655 }
656
Vitaly Buka4af611d2016-12-04 02:57:32657 if (!result.empty())
Vitaly Bukaf62fe472017-03-02 07:05:15658 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), random_);
Vitaly Buka4af611d2016-12-04 02:57:32659 return result;
660}
Vitaly Buka432b5452016-12-09 22:42:09661
Vitaly Bukaaf8136f2017-06-09 23:40:12662std::string Mutator::MutateUtf8String(const std::string& value,
663 size_t size_increase_hint) {
664 std::string str = MutateString(value, size_increase_hint);
665 FixUtf8String(&str, random_);
666 return str;
667}
668
Vitaly Buka432b5452016-12-09 22:42:09669} // namespace protobuf_mutator