blob: eaebbfbbd48928332ada9455cc7d868874114cb0 [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 Buka9dd2f8e2017-01-13 08:48:3115#include "src/protobuf_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 <iostream>
19#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"
24#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;
29using protobuf::EnumDescriptor;
30using protobuf::EnumValueDescriptor;
31using protobuf::FieldDescriptor;
32using protobuf::Message;
33using protobuf::OneofDescriptor;
34using protobuf::Reflection;
Vitaly Buka0e17fd72016-11-18 18:02:4635
Vitaly Buka0e17fd72016-11-18 18:02:4636namespace {
37
Vitaly Buka72019dc2016-12-15 03:17:2438const size_t kMaxInitializeDepth = 32;
39const size_t kDeletionThreshold = 128;
40const uint64_t kMutateWeight = 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 Buka4af611d2016-12-04 02:57:3253// Flips random bit in the buffer.
54void FlipBit(size_t size, uint8_t* bytes,
55 ProtobufMutator::RandomEngine* random) {
56 size_t bit = std::uniform_int_distribution<size_t>(0, size * 8 - 1)(*random);
57 bytes[bit / 8] ^= (1u << (bit % 8));
58}
Vitaly Buka781853c2016-11-22 07:09:3559
Vitaly Buka4af611d2016-12-04 02:57:3260// Flips random bit in the value.
61template <class T>
62T FlipBit(T value, ProtobufMutator::RandomEngine* random) {
63 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
64 return value;
65}
Vitaly Buka781853c2016-11-22 07:09:3566
Vitaly Buka4af611d2016-12-04 02:57:3267// Return random integer from [0, count)
Vitaly Buka781853c2016-11-22 07:09:3568size_t GetRandomIndex(ProtobufMutator::RandomEngine* random, size_t count) {
69 assert(count > 0);
Vitaly Bukabec52222016-12-09 22:29:3270 if (count == 1) return 0;
Vitaly Buka781853c2016-11-22 07:09:3571 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
72}
Vitaly Buka0e17fd72016-11-18 18:02:4673
Vitaly Buka91ad7b02016-12-12 23:41:4174struct CreateDefaultFieldTransformation {
75 template <class T>
76 void Apply(const FieldInstance& field) const {
77 T value;
78 field.GetDefault(&value);
79 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:3280 }
Vitaly Buka91ad7b02016-12-12 23:41:4181};
Vitaly Bukabec52222016-12-09 22:29:3282
Vitaly Buka91ad7b02016-12-12 23:41:4183struct DeleteFieldTransformation {
84 template <class T>
85 void Apply(const FieldInstance& field) const {
86 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:3287 }
Vitaly Bukabec52222016-12-09 22:29:3288};
89
Vitaly Bukaa3e59c72016-12-07 00:53:5690struct CopyFieldTransformation {
Vitaly Buka88712862017-02-27 06:21:3091 explicit CopyFieldTransformation(const ConstFieldInstance& field)
Vitaly Buka72019dc2016-12-15 03:17:2492 : source(field) {}
Vitaly Bukaa3e59c72016-12-07 00:53:5693
94 template <class T>
Vitaly Buka72019dc2016-12-15 03:17:2495 void Apply(const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:5696 T value;
97 source.Load(&value);
98 field.Store(value);
99 }
100
Vitaly Buka88712862017-02-27 06:21:30101 ConstFieldInstance source;
Vitaly Bukaa3e59c72016-12-07 00:53:56102};
103
Vitaly Bukaadfc27c2017-02-27 06:36:36104struct AppendFieldTransformation {
105 explicit AppendFieldTransformation(const ConstFieldInstance& field)
106 : source(field) {}
107
108 template <class T>
109 void Apply(const FieldInstance& field) const {
110 T value;
111 source.Load(&value);
112 field.Create(value);
113 }
114
115 ConstFieldInstance source;
116};
117
Vitaly Buka4af611d2016-12-04 02:57:32118// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35119class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17120 public:
Vitaly Buka72019dc2016-12-15 03:17:24121 MutationSampler(bool keep_initialized, size_t size_increase_hint,
Vitaly Buka781853c2016-11-22 07:09:35122 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-04 02:57:32123 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka72019dc2016-12-15 03:17:24124 if (size_increase_hint < kDeletionThreshold) {
Vitaly Buka4af611d2016-12-04 02:57:32125 // Avoid adding new field and prefer deleting fields if we getting close
126 // to the limit.
Vitaly Buka72019dc2016-12-15 03:17:24127 float adjustment = 0.5 * size_increase_hint / kDeletionThreshold;
128 add_weight_ *= adjustment;
129 delete_weight_ *= 1 - adjustment;
Vitaly Buka781853c2016-11-22 07:09:35130 }
131 Sample(message);
Vitaly Bukabec52222016-12-09 22:29:32132 assert(mutation() != Mutation::None);
Vitaly Bukac9d22482016-11-21 21:29:17133 }
134
Vitaly Buka4af611d2016-12-04 02:57:32135 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32136 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32137
138 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09139 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32140
141 private:
Vitaly Buka781853c2016-11-22 07:09:35142 void Sample(Message* message) {
143 const Descriptor* descriptor = message->GetDescriptor();
144 const Reflection* reflection = message->GetReflection();
145
146 int field_count = descriptor->field_count();
147 for (int i = 0; i < field_count; ++i) {
148 const FieldDescriptor* field = descriptor->field(i);
149 if (const OneofDescriptor* oneof = field->containing_oneof()) {
150 // Handle entire oneof group on the first field.
151 if (field->index_in_oneof() == 0) {
Vitaly Buka4af611d2016-12-04 02:57:32152 sampler_.Try(
153 add_weight_,
Vitaly Bukabec52222016-12-09 22:29:32154 {{message,
155 oneof->field(GetRandomIndex(random_, oneof->field_count()))},
Vitaly Buka4af611d2016-12-04 02:57:32156 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35157 if (const FieldDescriptor* field =
158 reflection->GetOneofFieldDescriptor(*message, oneof)) {
Vitaly Buka4af611d2016-12-04 02:57:32159 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32160 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
161 sampler_.Try(delete_weight_, {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24162 sampler_.Try(GetCopyWeight(field),
163 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35164 }
165 }
166 } else {
167 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32168 int field_size = reflection->FieldSize(*message, field);
169 sampler_.Try(add_weight_, {{message, field,
170 GetRandomIndex(random_, field_size + 1)},
171 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35172
Vitaly Bukabec52222016-12-09 22:29:32173 if (field_size) {
174 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka4af611d2016-12-04 02:57:32175 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32176 sampler_.Try(kMutateWeight,
177 {{message, field, random_index}, Mutation::Mutate});
178 sampler_.Try(delete_weight_,
179 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24180 sampler_.Try(GetCopyWeight(field),
Vitaly Bukaa3e59c72016-12-07 00:53:56181 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35182 }
183 } else {
184 if (reflection->HasField(*message, field)) {
Vitaly Buka4af611d2016-12-04 02:57:32185 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32186 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
Vitaly Buka4af611d2016-12-04 02:57:32187 if ((!field->is_required() || !keep_initialized_))
Vitaly Bukabec52222016-12-09 22:29:32188 sampler_.Try(delete_weight_,
189 {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24190 sampler_.Try(GetCopyWeight(field),
191 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35192 } else {
Vitaly Bukabec52222016-12-09 22:29:32193 sampler_.Try(add_weight_, {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35194 }
195 }
196 }
197
198 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
199 if (field->is_repeated()) {
200 const int field_size = reflection->FieldSize(*message, field);
201 for (int j = 0; j < field_size; ++j)
202 Sample(reflection->MutableRepeatedMessage(message, field, j));
203 } else if (reflection->HasField(*message, field)) {
204 Sample(reflection->MutableMessage(message, field));
205 }
206 }
207 }
208 }
209
Vitaly Buka72019dc2016-12-15 03:17:24210 uint64_t GetCopyWeight(const FieldDescriptor* field) const {
211 // Coping sub-messages can increase size significantly.
212 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
213 ? add_weight_
214 : kMutateWeight;
215 }
216
Vitaly Buka781853c2016-11-22 07:09:35217 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32218
219 // Adding and deleting are intrusive and expensive mutations, we'd like to do
Vitaly Buka432b5452016-12-09 22:42:09220 // them less often than field mutations.
Vitaly Buka781853c2016-11-22 07:09:35221 uint64_t add_weight_ = kMutateWeight / 10;
222 uint64_t delete_weight_ = kMutateWeight / 10;
Vitaly Buka781853c2016-11-22 07:09:35223
Vitaly Buka4af611d2016-12-04 02:57:32224 ProtobufMutator::RandomEngine* random_;
225
226 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41227 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32228 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41229
Vitaly Bukabec52222016-12-09 22:29:32230 FieldInstance field;
231 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32232 };
233 WeightedReservoirSampler<Result, ProtobufMutator::RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17234};
235
Vitaly Bukaa3e59c72016-12-07 00:53:56236// Selects random field of compatible type to use for clone mutations.
237class DataSourceSampler {
238 public:
Vitaly Buka88712862017-02-27 06:21:30239 DataSourceSampler(const ConstFieldInstance& match,
Vitaly Buka72019dc2016-12-15 03:17:24240 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Bukaa3e59c72016-12-07 00:53:56241 : match_(match), random_(random), sampler_(random) {
242 Sample(message);
243 }
244
245 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30246 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24247 assert(!IsEmpty());
248 return sampler_.selected();
249 }
250
251 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56252
253 private:
254 void Sample(Message* message) {
255 const Descriptor* descriptor = message->GetDescriptor();
256 const Reflection* reflection = message->GetReflection();
257
258 int field_count = descriptor->field_count();
259 for (int i = 0; i < field_count; ++i) {
260 const FieldDescriptor* field = descriptor->field(i);
261 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
262 if (field->is_repeated()) {
263 const int field_size = reflection->FieldSize(*message, field);
264 for (int j = 0; j < field_size; ++j) {
265 Sample(reflection->MutableRepeatedMessage(message, field, j));
266 }
267 } else if (reflection->HasField(*message, field)) {
268 Sample(reflection->MutableMessage(message, field));
269 }
270 }
271
272 if (field->cpp_type() != match_.cpp_type()) continue;
273 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
274 if (field->enum_type() != match_.enum_type()) continue;
275 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
276 if (field->message_type() != match_.message_type()) continue;
277 }
278
279 // TODO(vitalybuka) : make sure that values are different
280 if (field->is_repeated()) {
281 if (int field_size = reflection->FieldSize(*message, field)) {
282 sampler_.Try(field_size,
283 {message, field, GetRandomIndex(random_, field_size)});
284 }
285 } else {
286 if (reflection->HasField(*message, field)) {
287 sampler_.Try(1, {message, field});
288 }
289 }
290 }
291 }
292
Vitaly Buka88712862017-02-27 06:21:30293 ConstFieldInstance match_;
Vitaly Bukaa3e59c72016-12-07 00:53:56294 ProtobufMutator::RandomEngine* random_;
295
Vitaly Buka88712862017-02-27 06:21:30296 WeightedReservoirSampler<ConstFieldInstance, ProtobufMutator::RandomEngine>
Vitaly Buka72019dc2016-12-15 03:17:24297 sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56298};
299
Vitaly Buka0e17fd72016-11-18 18:02:46300} // namespace
301
Vitaly Buka5d013202017-02-25 00:50:11302class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09303 public:
Vitaly Buka5d013202017-02-25 00:50:11304 FieldMutator(size_t size_increase_hint, ProtobufMutator* mutator)
305 : size_increase_hint_(size_increase_hint), mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41306
Vitaly Buka91ad7b02016-12-12 23:41:41307 void Mutate(int32_t* value) const { *value = mutator_->MutateInt32(*value); }
308
309 void Mutate(int64_t* value) const { *value = mutator_->MutateInt64(*value); }
310
311 void Mutate(uint32_t* value) const {
312 *value = mutator_->MutateUInt32(*value);
313 }
314
315 void Mutate(uint64_t* value) const {
316 *value = mutator_->MutateUInt64(*value);
317 }
318
319 void Mutate(float* value) const { *value = mutator_->MutateFloat(*value); }
320
321 void Mutate(double* value) const { *value = mutator_->MutateDouble(*value); }
322
323 void Mutate(bool* value) const { *value = mutator_->MutateBool(*value); }
324
325 void Mutate(FieldInstance::Enum* value) const {
326 value->index = mutator_->MutateEnum(value->index, value->count);
327 assert(value->index < value->count);
328 }
329
330 void Mutate(std::string* value) const {
Vitaly Buka5d013202017-02-25 00:50:11331 *value = mutator_->MutateString(*value, size_increase_hint_);
Vitaly Buka91ad7b02016-12-12 23:41:41332 }
333
Vitaly Buka6c6dbbe2017-02-22 21:58:24334 void Mutate(std::unique_ptr<Message>*) const {
Vitaly Buka6c6dbbe2017-02-22 21:58:24335 }
Vitaly Buka432b5452016-12-09 22:42:09336
Vitaly Buka5d013202017-02-25 00:50:11337 private:
338 size_t size_increase_hint_;
Vitaly Buka432b5452016-12-09 22:42:09339 ProtobufMutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09340};
341
Vitaly Buka5d013202017-02-25 00:50:11342namespace {
343
344class MutateTransformation {
345 public:
346 MutateTransformation(size_t size_increase_hint, ProtobufMutator* mutator)
347 : mutator_(size_increase_hint, mutator) {}
348
349 template <class T>
350 void Apply(const FieldInstance& field) const {
351 T value;
352 field.Load(&value);
353 mutator_.Mutate(&value);
354 field.Store(value);
355 }
356
357 private:
358 FieldMutator mutator_;
359};
360
361class CreateFieldTransformation {
362 public:
363 CreateFieldTransformation(size_t size_increase_hint, ProtobufMutator* mutator)
364 : mutator_(size_increase_hint, mutator) {}
365
366 template <class T>
367 void Apply(const FieldInstance& field) const {
368 T value;
369 field.GetDefault(&value);
370 mutator_.Mutate(&value);
371 field.Create(value);
372 }
373
374 private:
375 FieldMutator mutator_;
376};
377
378} // namespace
379
Vitaly Bukaba129722016-12-15 01:29:15380ProtobufMutator::ProtobufMutator(uint32_t seed) : random_(seed) {}
Vitaly Buka432b5452016-12-09 22:42:09381
Vitaly Buka72019dc2016-12-15 03:17:24382void ProtobufMutator::Mutate(Message* message, size_t size_increase_hint) {
383 MutationSampler mutation(keep_initialized_, size_increase_hint, &random_,
384 message);
Vitaly Buka781853c2016-11-22 07:09:35385 switch (mutation.mutation()) {
386 case Mutation::None:
387 break;
388 case Mutation::Add:
Vitaly Buka5d013202017-02-25 00:50:11389 if (std::uniform_int_distribution<uint8_t>(0, 1)(random_)) {
390 mutation.field().Apply(
Vitaly Buka35df2e42017-02-25 09:17:25391 CreateFieldTransformation(size_increase_hint / 2, this));
Vitaly Buka5d013202017-02-25 00:50:11392 } else {
393 mutation.field().Apply(CreateDefaultFieldTransformation());
394 }
Vitaly Buka781853c2016-11-22 07:09:35395 break;
396 case Mutation::Mutate:
Vitaly Buka72019dc2016-12-15 03:17:24397 mutation.field().Apply(
Vitaly Buka35df2e42017-02-25 09:17:25398 MutateTransformation(size_increase_hint / 2, this));
Vitaly Buka781853c2016-11-22 07:09:35399 break;
400 case Mutation::Delete:
Vitaly Buka91ad7b02016-12-12 23:41:41401 mutation.field().Apply(DeleteFieldTransformation());
Vitaly Buka781853c2016-11-22 07:09:35402 break;
Vitaly Bukaa3e59c72016-12-07 00:53:56403 case Mutation::Copy: {
404 DataSourceSampler source(mutation.field(), &random_, message);
Vitaly Buka72019dc2016-12-15 03:17:24405 if (source.IsEmpty()) {
Vitaly Bukaa3e59c72016-12-07 00:53:56406 // Fallback to message deletion.
407 mutation.field().Apply(DeleteFieldTransformation());
408 break;
409 }
Vitaly Bukaa3e59c72016-12-07 00:53:56410 mutation.field().Apply(CopyFieldTransformation(source.field()));
411 break;
412 }
Vitaly Buka781853c2016-11-22 07:09:35413 default:
Vitaly Buka6c6dbbe2017-02-22 21:58:24414 assert(false && "unexpected mutation");
Vitaly Buka0e17fd72016-11-18 18:02:46415 }
416
Vitaly Buka781853c2016-11-22 07:09:35417 if (keep_initialized_ && !message->IsInitialized()) {
418 InitializeMessage(message, kMaxInitializeDepth);
419 assert(message->IsInitialized());
Vitaly Buka0e17fd72016-11-18 18:02:46420 }
Vitaly Buka00b61072016-10-19 23:22:51421}
422
Vitaly Bukaadfc27c2017-02-27 06:36:36423void ProtobufMutator::CrossOver(const protobuf::Message& message1,
424 protobuf::Message* message2) {
425 CrossOverImpl(message1, message2);
426
427 if (keep_initialized_ && !message2->IsInitialized()) {
428 InitializeMessage(message2, kMaxInitializeDepth);
429 assert(message2->IsInitialized());
430 }
431}
432
433void ProtobufMutator::CrossOverImpl(const protobuf::Message& message1,
434 protobuf::Message* message2) {
435 const Descriptor* descriptor = message2->GetDescriptor();
436 const Reflection* reflection = message2->GetReflection();
437 assert(message1.GetDescriptor() == descriptor);
438 assert(message1.GetReflection() == reflection);
439
440 for (int i = 0; i < descriptor->field_count(); ++i) {
441 const FieldDescriptor* field = descriptor->field(i);
442
443 if (field->is_repeated()) {
444 const int field_size1 = reflection->FieldSize(message1, field);
445 int field_size2 = reflection->FieldSize(*message2, field);
446 for (int j = 0; j < field_size1; ++j) {
447 ConstFieldInstance source(&message1, field, j);
448 FieldInstance destination(message2, field, field_size2++);
449 destination.Apply(AppendFieldTransformation(source));
450 }
451
452 assert(field_size2 == reflection->FieldSize(*message2, field));
453
454 // Shuffle
455 for (int j = 0; j < field_size2; ++j) {
456 if (int k = GetRandomIndex(&random_, field_size2 - j)) {
457 reflection->SwapElements(message2, field, j, j + k);
458 }
459 }
460
461 int keep = GetRandomIndex(&random_, field_size2 + 1);
462
463 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
464 int remove = field_size2 - keep;
465 // Cross some message to keep with messages to remove.
466 int cross = GetRandomIndex(&random_, std::min(keep, remove) + 1);
467 for (int j = 0; j < cross; ++j) {
468 int k = GetRandomIndex(&random_, keep);
469 int r = keep + GetRandomIndex(&random_, remove);
470 assert(k != r);
471 CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
472 reflection->MutableRepeatedMessage(message2, field, k));
473 }
474 }
475
476 for (int j = keep; j < field_size2; ++j)
477 reflection->RemoveLast(message2, field);
478 assert(keep == reflection->FieldSize(*message2, field));
479
480 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
481 if (!reflection->HasField(message1, field)) {
482 if (GetRandomIndex(&random_, 2))
483 FieldInstance(message2, field).Apply(DeleteFieldTransformation());
484 } else if (!reflection->HasField(*message2, field)) {
485 if (GetRandomIndex(&random_, 2)) {
486 ConstFieldInstance source(&message1, field);
487 FieldInstance(message2, field).Apply(CopyFieldTransformation(source));
488 }
489 } else {
490 CrossOverImpl(reflection->GetMessage(message1, field),
491 reflection->MutableMessage(message2, field));
492 }
493 } else {
494 if (GetRandomIndex(&random_, 2)) {
495 if (reflection->HasField(message1, field)) {
496 ConstFieldInstance source(&message1, field);
497 FieldInstance(message2, field).Apply(CopyFieldTransformation(source));
498 } else {
499 FieldInstance(message2, field).Apply(DeleteFieldTransformation());
500 }
501 }
502 }
503 }
504}
505
Vitaly Buka72019dc2016-12-15 03:17:24506void ProtobufMutator::InitializeMessage(Message* message, size_t max_depth) {
Vitaly Buka781853c2016-11-22 07:09:35507 assert(keep_initialized_);
Vitaly Buka432b5452016-12-09 22:42:09508 // It's pointless but possible to have infinite recursion of required
509 // messages.
510 assert(max_depth);
Vitaly Buka13245af2016-11-18 21:20:12511 const Descriptor* descriptor = message->GetDescriptor();
512 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12513 for (int i = 0; i < descriptor->field_count(); ++i) {
514 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka91ad7b02016-12-12 23:41:41515 if (field->is_required() && !reflection->HasField(*message, field))
516 FieldInstance(message, field).Apply(CreateDefaultFieldTransformation());
Vitaly Buka13245af2016-11-18 21:20:12517
Vitaly Buka781853c2016-11-22 07:09:35518 if (max_depth > 0 &&
519 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka2cfe02b2016-11-19 00:34:09520 if (field->is_repeated()) {
521 const int field_size = reflection->FieldSize(*message, field);
522 for (int j = 0; j < field_size; ++j) {
523 Message* nested_message =
524 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Buka781853c2016-11-22 07:09:35525 if (!nested_message->IsInitialized())
526 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09527 }
528 } else if (reflection->HasField(*message, field)) {
529 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Buka781853c2016-11-22 07:09:35530 if (!nested_message->IsInitialized())
531 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12532 }
533 }
534 }
535}
Vitaly Buka4af611d2016-12-04 02:57:32536
537int32_t ProtobufMutator::MutateInt32(int32_t value) {
538 return FlipBit(value, &random_);
539}
540
541int64_t ProtobufMutator::MutateInt64(int64_t value) {
542 return FlipBit(value, &random_);
543}
544
545uint32_t ProtobufMutator::MutateUInt32(uint32_t value) {
546 return FlipBit(value, &random_);
547}
548
549uint64_t ProtobufMutator::MutateUInt64(uint64_t value) {
550 return FlipBit(value, &random_);
551}
552
553float ProtobufMutator::MutateFloat(float value) {
554 return FlipBit(value, &random_);
555}
556
557double ProtobufMutator::MutateDouble(double value) {
558 return FlipBit(value, &random_);
559}
560
561bool ProtobufMutator::MutateBool(bool value) {
562 return std::uniform_int_distribution<uint8_t>(0, 1)(random_);
563}
564
565size_t ProtobufMutator::MutateEnum(size_t index, size_t item_count) {
566 return (index +
567 std::uniform_int_distribution<uint8_t>(1, item_count - 1)(random_)) %
568 item_count;
569}
570
571std::string ProtobufMutator::MutateString(const std::string& value,
Vitaly Buka5d013202017-02-25 00:50:11572 size_t size_increase_hint) {
573 std::uniform_int_distribution<uint8_t> distrib(0, 1);
Vitaly Buka4af611d2016-12-04 02:57:32574 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11575
576 while (!result.empty() && distrib(*random())) {
Vitaly Buka432b5452016-12-09 22:42:09577 result.erase(GetRandomIndex(&random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09578 }
579
Vitaly Buka5d013202017-02-25 00:50:11580 while (result.size() < size_increase_hint && distrib(*random())) {
Vitaly Buka432b5452016-12-09 22:42:09581 size_t index = GetRandomIndex(&random_, result.size() + 1);
Vitaly Buka5d013202017-02-25 00:50:11582 result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09583 }
584
Vitaly Buka4af611d2016-12-04 02:57:32585 if (!result.empty())
586 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
587 return result;
588}
Vitaly Buka432b5452016-12-09 22:42:09589
590} // namespace protobuf_mutator