blob: 2c23e445d66d79ca205d8aadb1badae1081e6c8a [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 Buka6c6dbbe2017-02-22 21:58:2426using protobuf::Descriptor;
27using protobuf::EnumDescriptor;
28using protobuf::EnumValueDescriptor;
29using protobuf::FieldDescriptor;
30using protobuf::Message;
31using protobuf::OneofDescriptor;
32using protobuf::Reflection;
Vitaly Buka0e17fd72016-11-18 18:02:4633
Vitaly Buka432b5452016-12-09 22:42:0934namespace protobuf_mutator {
35
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 Buka72019dc2016-12-15 03:17:2491 explicit CopyFieldTransformation(const FieldInstance& field)
92 : 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 Buka72019dc2016-12-15 03:17:24101 FieldInstance source;
Vitaly Bukaa3e59c72016-12-07 00:53:56102};
103
Vitaly Buka4af611d2016-12-04 02:57:32104// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35105class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17106 public:
Vitaly Buka72019dc2016-12-15 03:17:24107 MutationSampler(bool keep_initialized, size_t size_increase_hint,
Vitaly Buka781853c2016-11-22 07:09:35108 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-04 02:57:32109 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka72019dc2016-12-15 03:17:24110 if (size_increase_hint < kDeletionThreshold) {
Vitaly Buka4af611d2016-12-04 02:57:32111 // Avoid adding new field and prefer deleting fields if we getting close
112 // to the limit.
Vitaly Buka72019dc2016-12-15 03:17:24113 float adjustment = 0.5 * size_increase_hint / kDeletionThreshold;
114 add_weight_ *= adjustment;
115 delete_weight_ *= 1 - adjustment;
Vitaly Buka781853c2016-11-22 07:09:35116 }
117 Sample(message);
Vitaly Bukabec52222016-12-09 22:29:32118 assert(mutation() != Mutation::None);
Vitaly Bukac9d22482016-11-21 21:29:17119 }
120
Vitaly Buka4af611d2016-12-04 02:57:32121 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32122 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32123
124 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09125 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32126
127 private:
Vitaly Buka781853c2016-11-22 07:09:35128 void Sample(Message* message) {
129 const Descriptor* descriptor = message->GetDescriptor();
130 const Reflection* reflection = message->GetReflection();
131
132 int field_count = descriptor->field_count();
133 for (int i = 0; i < field_count; ++i) {
134 const FieldDescriptor* field = descriptor->field(i);
135 if (const OneofDescriptor* oneof = field->containing_oneof()) {
136 // Handle entire oneof group on the first field.
137 if (field->index_in_oneof() == 0) {
Vitaly Buka4af611d2016-12-04 02:57:32138 sampler_.Try(
139 add_weight_,
Vitaly Bukabec52222016-12-09 22:29:32140 {{message,
141 oneof->field(GetRandomIndex(random_, oneof->field_count()))},
Vitaly Buka4af611d2016-12-04 02:57:32142 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35143 if (const FieldDescriptor* field =
144 reflection->GetOneofFieldDescriptor(*message, oneof)) {
Vitaly Buka4af611d2016-12-04 02:57:32145 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32146 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
147 sampler_.Try(delete_weight_, {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24148 sampler_.Try(GetCopyWeight(field),
149 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35150 }
151 }
152 } else {
153 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32154 int field_size = reflection->FieldSize(*message, field);
155 sampler_.Try(add_weight_, {{message, field,
156 GetRandomIndex(random_, field_size + 1)},
157 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35158
Vitaly Bukabec52222016-12-09 22:29:32159 if (field_size) {
160 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka4af611d2016-12-04 02:57:32161 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32162 sampler_.Try(kMutateWeight,
163 {{message, field, random_index}, Mutation::Mutate});
164 sampler_.Try(delete_weight_,
165 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24166 sampler_.Try(GetCopyWeight(field),
Vitaly Bukaa3e59c72016-12-07 00:53:56167 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35168 }
169 } else {
170 if (reflection->HasField(*message, field)) {
Vitaly Buka4af611d2016-12-04 02:57:32171 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32172 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
Vitaly Buka4af611d2016-12-04 02:57:32173 if ((!field->is_required() || !keep_initialized_))
Vitaly Bukabec52222016-12-09 22:29:32174 sampler_.Try(delete_weight_,
175 {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24176 sampler_.Try(GetCopyWeight(field),
177 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35178 } else {
Vitaly Bukabec52222016-12-09 22:29:32179 sampler_.Try(add_weight_, {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35180 }
181 }
182 }
183
184 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
185 if (field->is_repeated()) {
186 const int field_size = reflection->FieldSize(*message, field);
187 for (int j = 0; j < field_size; ++j)
188 Sample(reflection->MutableRepeatedMessage(message, field, j));
189 } else if (reflection->HasField(*message, field)) {
190 Sample(reflection->MutableMessage(message, field));
191 }
192 }
193 }
194 }
195
Vitaly Buka72019dc2016-12-15 03:17:24196 uint64_t GetCopyWeight(const FieldDescriptor* field) const {
197 // Coping sub-messages can increase size significantly.
198 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
199 ? add_weight_
200 : kMutateWeight;
201 }
202
Vitaly Buka781853c2016-11-22 07:09:35203 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32204
205 // Adding and deleting are intrusive and expensive mutations, we'd like to do
Vitaly Buka432b5452016-12-09 22:42:09206 // them less often than field mutations.
Vitaly Buka781853c2016-11-22 07:09:35207 uint64_t add_weight_ = kMutateWeight / 10;
208 uint64_t delete_weight_ = kMutateWeight / 10;
Vitaly Buka781853c2016-11-22 07:09:35209
Vitaly Buka4af611d2016-12-04 02:57:32210 ProtobufMutator::RandomEngine* random_;
211
212 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41213 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32214 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41215
Vitaly Bukabec52222016-12-09 22:29:32216 FieldInstance field;
217 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32218 };
219 WeightedReservoirSampler<Result, ProtobufMutator::RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17220};
221
Vitaly Bukaa3e59c72016-12-07 00:53:56222// Selects random field of compatible type to use for clone mutations.
223class DataSourceSampler {
224 public:
Vitaly Buka72019dc2016-12-15 03:17:24225 DataSourceSampler(const FieldInstance& match,
226 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Bukaa3e59c72016-12-07 00:53:56227 : match_(match), random_(random), sampler_(random) {
228 Sample(message);
229 }
230
231 // Returns selected field.
Vitaly Buka72019dc2016-12-15 03:17:24232 const FieldInstance& field() const {
233 assert(!IsEmpty());
234 return sampler_.selected();
235 }
236
237 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56238
239 private:
240 void Sample(Message* message) {
241 const Descriptor* descriptor = message->GetDescriptor();
242 const Reflection* reflection = message->GetReflection();
243
244 int field_count = descriptor->field_count();
245 for (int i = 0; i < field_count; ++i) {
246 const FieldDescriptor* field = descriptor->field(i);
247 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
248 if (field->is_repeated()) {
249 const int field_size = reflection->FieldSize(*message, field);
250 for (int j = 0; j < field_size; ++j) {
251 Sample(reflection->MutableRepeatedMessage(message, field, j));
252 }
253 } else if (reflection->HasField(*message, field)) {
254 Sample(reflection->MutableMessage(message, field));
255 }
256 }
257
258 if (field->cpp_type() != match_.cpp_type()) continue;
259 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
260 if (field->enum_type() != match_.enum_type()) continue;
261 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
262 if (field->message_type() != match_.message_type()) continue;
263 }
264
265 // TODO(vitalybuka) : make sure that values are different
266 if (field->is_repeated()) {
267 if (int field_size = reflection->FieldSize(*message, field)) {
268 sampler_.Try(field_size,
269 {message, field, GetRandomIndex(random_, field_size)});
270 }
271 } else {
272 if (reflection->HasField(*message, field)) {
273 sampler_.Try(1, {message, field});
274 }
275 }
276 }
277 }
278
Vitaly Buka72019dc2016-12-15 03:17:24279 FieldInstance match_;
Vitaly Bukaa3e59c72016-12-07 00:53:56280 ProtobufMutator::RandomEngine* random_;
281
Vitaly Buka72019dc2016-12-15 03:17:24282 WeightedReservoirSampler<FieldInstance, ProtobufMutator::RandomEngine>
283 sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56284};
285
Vitaly Buka0e17fd72016-11-18 18:02:46286} // namespace
287
Vitaly Buka91ad7b02016-12-12 23:41:41288class MutateTransformation {
Vitaly Buka432b5452016-12-09 22:42:09289 public:
Vitaly Buka91ad7b02016-12-12 23:41:41290 MutateTransformation(size_t allowed_growth, ProtobufMutator* mutator)
291 : allowed_growth_(allowed_growth), mutator_(mutator) {}
292
293 template <class T>
294 void Apply(const FieldInstance& field) const {
295 T value;
296 field.Load(&value);
297 Mutate(&value);
298 field.Store(value);
Vitaly Buka432b5452016-12-09 22:42:09299 }
Vitaly Buka00b61072016-10-19 23:22:51300
Vitaly Buka432b5452016-12-09 22:42:09301 private:
Vitaly Buka91ad7b02016-12-12 23:41:41302 void Mutate(int32_t* value) const { *value = mutator_->MutateInt32(*value); }
303
304 void Mutate(int64_t* value) const { *value = mutator_->MutateInt64(*value); }
305
306 void Mutate(uint32_t* value) const {
307 *value = mutator_->MutateUInt32(*value);
308 }
309
310 void Mutate(uint64_t* value) const {
311 *value = mutator_->MutateUInt64(*value);
312 }
313
314 void Mutate(float* value) const { *value = mutator_->MutateFloat(*value); }
315
316 void Mutate(double* value) const { *value = mutator_->MutateDouble(*value); }
317
318 void Mutate(bool* value) const { *value = mutator_->MutateBool(*value); }
319
320 void Mutate(FieldInstance::Enum* value) const {
321 value->index = mutator_->MutateEnum(value->index, value->count);
322 assert(value->index < value->count);
323 }
324
325 void Mutate(std::string* value) const {
326 *value = mutator_->MutateString(*value, allowed_growth_);
327 }
328
Vitaly Buka6c6dbbe2017-02-22 21:58:24329 void Mutate(std::unique_ptr<Message>*) const {
330 assert(false && "Unexpected");
331 }
Vitaly Buka432b5452016-12-09 22:42:09332
333 size_t allowed_growth_;
334 ProtobufMutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09335};
336
Vitaly Bukaba129722016-12-15 01:29:15337ProtobufMutator::ProtobufMutator(uint32_t seed) : random_(seed) {}
Vitaly Buka432b5452016-12-09 22:42:09338
Vitaly Buka72019dc2016-12-15 03:17:24339void ProtobufMutator::Mutate(Message* message, size_t size_increase_hint) {
340 MutationSampler mutation(keep_initialized_, size_increase_hint, &random_,
341 message);
Vitaly Buka781853c2016-11-22 07:09:35342 switch (mutation.mutation()) {
343 case Mutation::None:
344 break;
345 case Mutation::Add:
Vitaly Buka91ad7b02016-12-12 23:41:41346 mutation.field().Apply(CreateDefaultFieldTransformation());
Vitaly Buka781853c2016-11-22 07:09:35347 break;
348 case Mutation::Mutate:
Vitaly Buka72019dc2016-12-15 03:17:24349 mutation.field().Apply(
350 MutateTransformation(size_increase_hint / 4, this));
Vitaly Buka781853c2016-11-22 07:09:35351 break;
352 case Mutation::Delete:
Vitaly Buka91ad7b02016-12-12 23:41:41353 mutation.field().Apply(DeleteFieldTransformation());
Vitaly Buka781853c2016-11-22 07:09:35354 break;
Vitaly Bukaa3e59c72016-12-07 00:53:56355 case Mutation::Copy: {
356 DataSourceSampler source(mutation.field(), &random_, message);
Vitaly Buka72019dc2016-12-15 03:17:24357 if (source.IsEmpty()) {
Vitaly Bukaa3e59c72016-12-07 00:53:56358 // Fallback to message deletion.
359 mutation.field().Apply(DeleteFieldTransformation());
360 break;
361 }
Vitaly Bukaa3e59c72016-12-07 00:53:56362 mutation.field().Apply(CopyFieldTransformation(source.field()));
363 break;
364 }
Vitaly Buka781853c2016-11-22 07:09:35365 default:
Vitaly Buka6c6dbbe2017-02-22 21:58:24366 assert(false && "unexpected mutation");
Vitaly Buka0e17fd72016-11-18 18:02:46367 }
368
Vitaly Buka781853c2016-11-22 07:09:35369 if (keep_initialized_ && !message->IsInitialized()) {
370 InitializeMessage(message, kMaxInitializeDepth);
371 assert(message->IsInitialized());
Vitaly Buka0e17fd72016-11-18 18:02:46372 }
Vitaly Buka00b61072016-10-19 23:22:51373}
374
Vitaly Buka72019dc2016-12-15 03:17:24375void ProtobufMutator::InitializeMessage(Message* message, size_t max_depth) {
Vitaly Buka781853c2016-11-22 07:09:35376 assert(keep_initialized_);
Vitaly Buka432b5452016-12-09 22:42:09377 // It's pointless but possible to have infinite recursion of required
378 // messages.
379 assert(max_depth);
Vitaly Buka13245af2016-11-18 21:20:12380 const Descriptor* descriptor = message->GetDescriptor();
381 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12382 for (int i = 0; i < descriptor->field_count(); ++i) {
383 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka91ad7b02016-12-12 23:41:41384 if (field->is_required() && !reflection->HasField(*message, field))
385 FieldInstance(message, field).Apply(CreateDefaultFieldTransformation());
Vitaly Buka13245af2016-11-18 21:20:12386
Vitaly Buka781853c2016-11-22 07:09:35387 if (max_depth > 0 &&
388 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka2cfe02b2016-11-19 00:34:09389 if (field->is_repeated()) {
390 const int field_size = reflection->FieldSize(*message, field);
391 for (int j = 0; j < field_size; ++j) {
392 Message* nested_message =
393 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Buka781853c2016-11-22 07:09:35394 if (!nested_message->IsInitialized())
395 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09396 }
397 } else if (reflection->HasField(*message, field)) {
398 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Buka781853c2016-11-22 07:09:35399 if (!nested_message->IsInitialized())
400 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12401 }
402 }
403 }
404}
Vitaly Buka4af611d2016-12-04 02:57:32405
406int32_t ProtobufMutator::MutateInt32(int32_t value) {
407 return FlipBit(value, &random_);
408}
409
410int64_t ProtobufMutator::MutateInt64(int64_t value) {
411 return FlipBit(value, &random_);
412}
413
414uint32_t ProtobufMutator::MutateUInt32(uint32_t value) {
415 return FlipBit(value, &random_);
416}
417
418uint64_t ProtobufMutator::MutateUInt64(uint64_t value) {
419 return FlipBit(value, &random_);
420}
421
422float ProtobufMutator::MutateFloat(float value) {
423 return FlipBit(value, &random_);
424}
425
426double ProtobufMutator::MutateDouble(double value) {
427 return FlipBit(value, &random_);
428}
429
430bool ProtobufMutator::MutateBool(bool value) {
431 return std::uniform_int_distribution<uint8_t>(0, 1)(random_);
432}
433
434size_t ProtobufMutator::MutateEnum(size_t index, size_t item_count) {
435 return (index +
436 std::uniform_int_distribution<uint8_t>(1, item_count - 1)(random_)) %
437 item_count;
438}
439
440std::string ProtobufMutator::MutateString(const std::string& value,
441 size_t allowed_growth) {
442 std::string result = value;
Vitaly Buka4af611d2016-12-04 02:57:32443 int min_diff = result.empty() ? 0 : -1;
444 int max_diff = allowed_growth ? 1 : 0;
445 int diff = std::uniform_int_distribution<int>(min_diff, max_diff)(random_);
Vitaly Buka432b5452016-12-09 22:42:09446 if (diff == -1) {
447 result.erase(GetRandomIndex(&random_, result.size()), 1);
448 return result;
449 }
450
451 if (diff == 1) {
452 size_t index = GetRandomIndex(&random_, result.size() + 1);
453 result.insert(result.begin() + index, '\0');
454 FlipBit(1, reinterpret_cast<uint8_t*>(&result[index]), &random_);
455 return result;
456 }
457
Vitaly Buka4af611d2016-12-04 02:57:32458 if (!result.empty())
459 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
460 return result;
461}
Vitaly Buka432b5452016-12-09 22:42:09462
463} // namespace protobuf_mutator