blob: efe44156e249bbfbc0182f77b538ff080be61a43 [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 Bukaf047a002017-01-13 07:57:0023#include "google/protobuf/message.h"
Vitaly Buka9dd2f8e2017-01-13 08:48:3124#include "src/field_instance.h"
25#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 23:22:5126
Vitaly Buka0e17fd72016-11-18 18:02:4627using google::protobuf::Descriptor;
Vitaly Buka2cfe02b2016-11-19 00:34:0928using google::protobuf::EnumDescriptor;
29using google::protobuf::EnumValueDescriptor;
30using google::protobuf::FieldDescriptor;
31using google::protobuf::Message;
Vitaly Buka0e17fd72016-11-18 18:02:4632using google::protobuf::OneofDescriptor;
Vitaly Buka2cfe02b2016-11-19 00:34:0933using google::protobuf::Reflection;
Vitaly Buka0e17fd72016-11-18 18:02:4634
Vitaly Buka432b5452016-12-09 22:42:0935namespace protobuf_mutator {
36
Vitaly Buka0e17fd72016-11-18 18:02:4637namespace {
38
Vitaly Buka72019dc2016-12-15 03:17:2439const size_t kMaxInitializeDepth = 32;
40const size_t kDeletionThreshold = 128;
41const uint64_t kMutateWeight = 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 Buka4af611d2016-12-04 02:57:3254// Flips random bit in the buffer.
55void FlipBit(size_t size, uint8_t* bytes,
56 ProtobufMutator::RandomEngine* random) {
57 size_t bit = std::uniform_int_distribution<size_t>(0, size * 8 - 1)(*random);
58 bytes[bit / 8] ^= (1u << (bit % 8));
59}
Vitaly Buka781853c2016-11-22 07:09:3560
Vitaly Buka4af611d2016-12-04 02:57:3261// Flips random bit in the value.
62template <class T>
63T FlipBit(T value, ProtobufMutator::RandomEngine* random) {
64 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
65 return value;
66}
Vitaly Buka781853c2016-11-22 07:09:3567
Vitaly Buka4af611d2016-12-04 02:57:3268// Return random integer from [0, count)
Vitaly Buka781853c2016-11-22 07:09:3569size_t GetRandomIndex(ProtobufMutator::RandomEngine* random, size_t count) {
70 assert(count > 0);
Vitaly Bukabec52222016-12-09 22:29:3271 if (count == 1) return 0;
Vitaly Buka781853c2016-11-22 07:09:3572 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
73}
Vitaly Buka0e17fd72016-11-18 18:02:4674
Vitaly Buka91ad7b02016-12-12 23:41:4175struct CreateDefaultFieldTransformation {
76 template <class T>
77 void Apply(const FieldInstance& field) const {
78 T value;
79 field.GetDefault(&value);
80 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:3281 }
Vitaly Buka91ad7b02016-12-12 23:41:4182};
Vitaly Bukabec52222016-12-09 22:29:3283
Vitaly Buka91ad7b02016-12-12 23:41:4184struct DeleteFieldTransformation {
85 template <class T>
86 void Apply(const FieldInstance& field) const {
87 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:3288 }
Vitaly Bukabec52222016-12-09 22:29:3289};
90
Vitaly Bukaa3e59c72016-12-07 00:53:5691struct CopyFieldTransformation {
Vitaly Buka72019dc2016-12-15 03:17:2492 explicit CopyFieldTransformation(const FieldInstance& field)
93 : source(field) {}
Vitaly Bukaa3e59c72016-12-07 00:53:5694
95 template <class T>
Vitaly Buka72019dc2016-12-15 03:17:2496 void Apply(const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:5697 T value;
98 source.Load(&value);
99 field.Store(value);
100 }
101
Vitaly Buka72019dc2016-12-15 03:17:24102 FieldInstance source;
Vitaly Bukaa3e59c72016-12-07 00:53:56103};
104
Vitaly Buka4af611d2016-12-04 02:57:32105// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35106class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17107 public:
Vitaly Buka72019dc2016-12-15 03:17:24108 MutationSampler(bool keep_initialized, size_t size_increase_hint,
Vitaly Buka781853c2016-11-22 07:09:35109 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-04 02:57:32110 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka72019dc2016-12-15 03:17:24111 if (size_increase_hint < kDeletionThreshold) {
Vitaly Buka4af611d2016-12-04 02:57:32112 // Avoid adding new field and prefer deleting fields if we getting close
113 // to the limit.
Vitaly Buka72019dc2016-12-15 03:17:24114 float adjustment = 0.5 * size_increase_hint / kDeletionThreshold;
115 add_weight_ *= adjustment;
116 delete_weight_ *= 1 - adjustment;
Vitaly Buka781853c2016-11-22 07:09:35117 }
118 Sample(message);
Vitaly Bukabec52222016-12-09 22:29:32119 assert(mutation() != Mutation::None);
Vitaly Bukac9d22482016-11-21 21:29:17120 }
121
Vitaly Buka4af611d2016-12-04 02:57:32122 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32123 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32124
125 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09126 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32127
128 private:
Vitaly Buka781853c2016-11-22 07:09:35129 void Sample(Message* message) {
130 const Descriptor* descriptor = message->GetDescriptor();
131 const Reflection* reflection = message->GetReflection();
132
133 int field_count = descriptor->field_count();
134 for (int i = 0; i < field_count; ++i) {
135 const FieldDescriptor* field = descriptor->field(i);
136 if (const OneofDescriptor* oneof = field->containing_oneof()) {
137 // Handle entire oneof group on the first field.
138 if (field->index_in_oneof() == 0) {
Vitaly Buka4af611d2016-12-04 02:57:32139 sampler_.Try(
140 add_weight_,
Vitaly Bukabec52222016-12-09 22:29:32141 {{message,
142 oneof->field(GetRandomIndex(random_, oneof->field_count()))},
Vitaly Buka4af611d2016-12-04 02:57:32143 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35144 if (const FieldDescriptor* field =
145 reflection->GetOneofFieldDescriptor(*message, oneof)) {
Vitaly Buka4af611d2016-12-04 02:57:32146 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32147 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
148 sampler_.Try(delete_weight_, {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24149 sampler_.Try(GetCopyWeight(field),
150 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35151 }
152 }
153 } else {
154 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32155 int field_size = reflection->FieldSize(*message, field);
156 sampler_.Try(add_weight_, {{message, field,
157 GetRandomIndex(random_, field_size + 1)},
158 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35159
Vitaly Bukabec52222016-12-09 22:29:32160 if (field_size) {
161 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka4af611d2016-12-04 02:57:32162 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32163 sampler_.Try(kMutateWeight,
164 {{message, field, random_index}, Mutation::Mutate});
165 sampler_.Try(delete_weight_,
166 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24167 sampler_.Try(GetCopyWeight(field),
Vitaly Bukaa3e59c72016-12-07 00:53:56168 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35169 }
170 } else {
171 if (reflection->HasField(*message, field)) {
Vitaly Buka4af611d2016-12-04 02:57:32172 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32173 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
Vitaly Buka4af611d2016-12-04 02:57:32174 if ((!field->is_required() || !keep_initialized_))
Vitaly Bukabec52222016-12-09 22:29:32175 sampler_.Try(delete_weight_,
176 {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24177 sampler_.Try(GetCopyWeight(field),
178 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35179 } else {
Vitaly Bukabec52222016-12-09 22:29:32180 sampler_.Try(add_weight_, {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35181 }
182 }
183 }
184
185 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
186 if (field->is_repeated()) {
187 const int field_size = reflection->FieldSize(*message, field);
188 for (int j = 0; j < field_size; ++j)
189 Sample(reflection->MutableRepeatedMessage(message, field, j));
190 } else if (reflection->HasField(*message, field)) {
191 Sample(reflection->MutableMessage(message, field));
192 }
193 }
194 }
195 }
196
Vitaly Buka72019dc2016-12-15 03:17:24197 uint64_t GetCopyWeight(const FieldDescriptor* field) const {
198 // Coping sub-messages can increase size significantly.
199 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
200 ? add_weight_
201 : kMutateWeight;
202 }
203
Vitaly Buka781853c2016-11-22 07:09:35204 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32205
206 // Adding and deleting are intrusive and expensive mutations, we'd like to do
Vitaly Buka432b5452016-12-09 22:42:09207 // them less often than field mutations.
Vitaly Buka781853c2016-11-22 07:09:35208 uint64_t add_weight_ = kMutateWeight / 10;
209 uint64_t delete_weight_ = kMutateWeight / 10;
Vitaly Buka781853c2016-11-22 07:09:35210
Vitaly Buka4af611d2016-12-04 02:57:32211 ProtobufMutator::RandomEngine* random_;
212
213 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41214 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32215 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41216
Vitaly Bukabec52222016-12-09 22:29:32217 FieldInstance field;
218 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32219 };
220 WeightedReservoirSampler<Result, ProtobufMutator::RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17221};
222
Vitaly Bukaa3e59c72016-12-07 00:53:56223// Selects random field of compatible type to use for clone mutations.
224class DataSourceSampler {
225 public:
Vitaly Buka72019dc2016-12-15 03:17:24226 DataSourceSampler(const FieldInstance& match,
227 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Bukaa3e59c72016-12-07 00:53:56228 : match_(match), random_(random), sampler_(random) {
229 Sample(message);
230 }
231
232 // Returns selected field.
Vitaly Buka72019dc2016-12-15 03:17:24233 const FieldInstance& field() const {
234 assert(!IsEmpty());
235 return sampler_.selected();
236 }
237
238 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56239
240 private:
241 void Sample(Message* message) {
242 const Descriptor* descriptor = message->GetDescriptor();
243 const Reflection* reflection = message->GetReflection();
244
245 int field_count = descriptor->field_count();
246 for (int i = 0; i < field_count; ++i) {
247 const FieldDescriptor* field = descriptor->field(i);
248 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
249 if (field->is_repeated()) {
250 const int field_size = reflection->FieldSize(*message, field);
251 for (int j = 0; j < field_size; ++j) {
252 Sample(reflection->MutableRepeatedMessage(message, field, j));
253 }
254 } else if (reflection->HasField(*message, field)) {
255 Sample(reflection->MutableMessage(message, field));
256 }
257 }
258
259 if (field->cpp_type() != match_.cpp_type()) continue;
260 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
261 if (field->enum_type() != match_.enum_type()) continue;
262 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
263 if (field->message_type() != match_.message_type()) continue;
264 }
265
266 // TODO(vitalybuka) : make sure that values are different
267 if (field->is_repeated()) {
268 if (int field_size = reflection->FieldSize(*message, field)) {
269 sampler_.Try(field_size,
270 {message, field, GetRandomIndex(random_, field_size)});
271 }
272 } else {
273 if (reflection->HasField(*message, field)) {
274 sampler_.Try(1, {message, field});
275 }
276 }
277 }
278 }
279
Vitaly Buka72019dc2016-12-15 03:17:24280 FieldInstance match_;
Vitaly Bukaa3e59c72016-12-07 00:53:56281 ProtobufMutator::RandomEngine* random_;
282
Vitaly Buka72019dc2016-12-15 03:17:24283 WeightedReservoirSampler<FieldInstance, ProtobufMutator::RandomEngine>
284 sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56285};
286
Vitaly Buka0e17fd72016-11-18 18:02:46287} // namespace
288
Vitaly Buka91ad7b02016-12-12 23:41:41289class MutateTransformation {
Vitaly Buka432b5452016-12-09 22:42:09290 public:
Vitaly Buka91ad7b02016-12-12 23:41:41291 MutateTransformation(size_t allowed_growth, ProtobufMutator* mutator)
292 : allowed_growth_(allowed_growth), mutator_(mutator) {}
293
294 template <class T>
295 void Apply(const FieldInstance& field) const {
296 T value;
297 field.Load(&value);
298 Mutate(&value);
299 field.Store(value);
Vitaly Buka432b5452016-12-09 22:42:09300 }
Vitaly Buka00b61072016-10-19 23:22:51301
Vitaly Buka432b5452016-12-09 22:42:09302 private:
Vitaly Buka91ad7b02016-12-12 23:41:41303 void Mutate(int32_t* value) const { *value = mutator_->MutateInt32(*value); }
304
305 void Mutate(int64_t* value) const { *value = mutator_->MutateInt64(*value); }
306
307 void Mutate(uint32_t* value) const {
308 *value = mutator_->MutateUInt32(*value);
309 }
310
311 void Mutate(uint64_t* value) const {
312 *value = mutator_->MutateUInt64(*value);
313 }
314
315 void Mutate(float* value) const { *value = mutator_->MutateFloat(*value); }
316
317 void Mutate(double* value) const { *value = mutator_->MutateDouble(*value); }
318
319 void Mutate(bool* value) const { *value = mutator_->MutateBool(*value); }
320
321 void Mutate(FieldInstance::Enum* value) const {
322 value->index = mutator_->MutateEnum(value->index, value->count);
323 assert(value->index < value->count);
324 }
325
326 void Mutate(std::string* value) const {
327 *value = mutator_->MutateString(*value, allowed_growth_);
328 }
329
330 void Mutate(std::unique_ptr<Message>*) const { assert(!"Unexpected"); }
Vitaly Buka432b5452016-12-09 22:42:09331
332 size_t allowed_growth_;
333 ProtobufMutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09334};
335
Vitaly Bukaba129722016-12-15 01:29:15336ProtobufMutator::ProtobufMutator(uint32_t seed) : random_(seed) {}
Vitaly Buka432b5452016-12-09 22:42:09337
Vitaly Buka72019dc2016-12-15 03:17:24338void ProtobufMutator::Mutate(Message* message, size_t size_increase_hint) {
339 MutationSampler mutation(keep_initialized_, size_increase_hint, &random_,
340 message);
Vitaly Buka781853c2016-11-22 07:09:35341 switch (mutation.mutation()) {
342 case Mutation::None:
343 break;
344 case Mutation::Add:
Vitaly Buka91ad7b02016-12-12 23:41:41345 mutation.field().Apply(CreateDefaultFieldTransformation());
Vitaly Buka781853c2016-11-22 07:09:35346 break;
347 case Mutation::Mutate:
Vitaly Buka72019dc2016-12-15 03:17:24348 mutation.field().Apply(
349 MutateTransformation(size_increase_hint / 4, this));
Vitaly Buka781853c2016-11-22 07:09:35350 break;
351 case Mutation::Delete:
Vitaly Buka91ad7b02016-12-12 23:41:41352 mutation.field().Apply(DeleteFieldTransformation());
Vitaly Buka781853c2016-11-22 07:09:35353 break;
Vitaly Bukaa3e59c72016-12-07 00:53:56354 case Mutation::Copy: {
355 DataSourceSampler source(mutation.field(), &random_, message);
Vitaly Buka72019dc2016-12-15 03:17:24356 if (source.IsEmpty()) {
Vitaly Bukaa3e59c72016-12-07 00:53:56357 // Fallback to message deletion.
358 mutation.field().Apply(DeleteFieldTransformation());
359 break;
360 }
Vitaly Bukaa3e59c72016-12-07 00:53:56361 mutation.field().Apply(CopyFieldTransformation(source.field()));
362 break;
363 }
Vitaly Buka781853c2016-11-22 07:09:35364 default:
365 assert(!"unexpected mutation");
Vitaly Buka0e17fd72016-11-18 18:02:46366 }
367
Vitaly Buka781853c2016-11-22 07:09:35368 if (keep_initialized_ && !message->IsInitialized()) {
369 InitializeMessage(message, kMaxInitializeDepth);
370 assert(message->IsInitialized());
Vitaly Buka0e17fd72016-11-18 18:02:46371 }
Vitaly Buka00b61072016-10-19 23:22:51372}
373
Vitaly Buka72019dc2016-12-15 03:17:24374void ProtobufMutator::InitializeMessage(Message* message, size_t max_depth) {
Vitaly Buka781853c2016-11-22 07:09:35375 assert(keep_initialized_);
Vitaly Buka432b5452016-12-09 22:42:09376 // It's pointless but possible to have infinite recursion of required
377 // messages.
378 assert(max_depth);
Vitaly Buka13245af2016-11-18 21:20:12379 const Descriptor* descriptor = message->GetDescriptor();
380 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12381 for (int i = 0; i < descriptor->field_count(); ++i) {
382 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka91ad7b02016-12-12 23:41:41383 if (field->is_required() && !reflection->HasField(*message, field))
384 FieldInstance(message, field).Apply(CreateDefaultFieldTransformation());
Vitaly Buka13245af2016-11-18 21:20:12385
Vitaly Buka781853c2016-11-22 07:09:35386 if (max_depth > 0 &&
387 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka2cfe02b2016-11-19 00:34:09388 if (field->is_repeated()) {
389 const int field_size = reflection->FieldSize(*message, field);
390 for (int j = 0; j < field_size; ++j) {
391 Message* nested_message =
392 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Buka781853c2016-11-22 07:09:35393 if (!nested_message->IsInitialized())
394 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09395 }
396 } else if (reflection->HasField(*message, field)) {
397 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Buka781853c2016-11-22 07:09:35398 if (!nested_message->IsInitialized())
399 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12400 }
401 }
402 }
403}
Vitaly Buka4af611d2016-12-04 02:57:32404
405int32_t ProtobufMutator::MutateInt32(int32_t value) {
406 return FlipBit(value, &random_);
407}
408
409int64_t ProtobufMutator::MutateInt64(int64_t value) {
410 return FlipBit(value, &random_);
411}
412
413uint32_t ProtobufMutator::MutateUInt32(uint32_t value) {
414 return FlipBit(value, &random_);
415}
416
417uint64_t ProtobufMutator::MutateUInt64(uint64_t value) {
418 return FlipBit(value, &random_);
419}
420
421float ProtobufMutator::MutateFloat(float value) {
422 return FlipBit(value, &random_);
423}
424
425double ProtobufMutator::MutateDouble(double value) {
426 return FlipBit(value, &random_);
427}
428
429bool ProtobufMutator::MutateBool(bool value) {
430 return std::uniform_int_distribution<uint8_t>(0, 1)(random_);
431}
432
433size_t ProtobufMutator::MutateEnum(size_t index, size_t item_count) {
434 return (index +
435 std::uniform_int_distribution<uint8_t>(1, item_count - 1)(random_)) %
436 item_count;
437}
438
439std::string ProtobufMutator::MutateString(const std::string& value,
440 size_t allowed_growth) {
441 std::string result = value;
Vitaly Buka4af611d2016-12-04 02:57:32442 int min_diff = result.empty() ? 0 : -1;
443 int max_diff = allowed_growth ? 1 : 0;
444 int diff = std::uniform_int_distribution<int>(min_diff, max_diff)(random_);
Vitaly Buka432b5452016-12-09 22:42:09445 if (diff == -1) {
446 result.erase(GetRandomIndex(&random_, result.size()), 1);
447 return result;
448 }
449
450 if (diff == 1) {
451 size_t index = GetRandomIndex(&random_, result.size() + 1);
452 result.insert(result.begin() + index, '\0');
453 FlipBit(1, reinterpret_cast<uint8_t*>(&result[index]), &random_);
454 return result;
455 }
456
Vitaly Buka4af611d2016-12-04 02:57:32457 if (!result.empty())
458 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
459 return result;
460}
Vitaly Buka432b5452016-12-09 22:42:09461
462} // namespace protobuf_mutator