blob: 993106578c64d6dff97a51325ac22dccb200a1b0 [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>
Allen-Webbc4fa5912018-09-07 22:53:3021#include <vector>
Vitaly Buka00b61072016-10-19 23:22:5122
Vitaly Buka9dd2f8e2017-01-13 08:48:3123#include "src/field_instance.h"
Vitaly Bukaaf8136f2017-06-09 23:40:1224#include "src/utf8_fix.h"
Vitaly Buka9dd2f8e2017-01-13 08:48:3125#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 23:22:5126
Vitaly Bukaf86815c2017-02-27 22:19:1927namespace protobuf_mutator {
28
Vitaly Buka6c6dbbe2017-02-22 21:58:2429using protobuf::Descriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2430using protobuf::FieldDescriptor;
Vitaly Buka796b1122017-03-03 22:42:0231using protobuf::FileDescriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2432using protobuf::Message;
33using protobuf::OneofDescriptor;
34using protobuf::Reflection;
Vitaly Buka4782c142017-03-04 08:12:3235using protobuf::util::MessageDifferencer;
Vitaly Buka796b1122017-03-03 22:42:0236using std::placeholders::_1;
Vitaly Buka0e17fd72016-11-18 18:02:4637
38namespace {
39
Vitaly Bukae4eae602017-09-29 00:28:1240const int kMaxInitializeDepth = 200;
Vitaly Buka329fa462017-03-15 23:52:1741const uint64_t kDefaultMutateWeight = 1000000;
Vitaly Buka0e17fd72016-11-18 18:02:4642
43enum class Mutation {
Vitaly Buka30de3092016-11-18 19:39:0744 None,
Vitaly Buka4af611d2016-12-04 02:57:3245 Add, // Adds new field with default value.
46 Mutate, // Mutates field contents.
47 Delete, // Deletes field.
Vitaly Bukaa3e59c72016-12-07 00:53:5648 Copy, // Copy values copied from another field.
Vitaly Buka4af611d2016-12-04 02:57:3249
Vitaly Buka432b5452016-12-09 22:42:0950 // TODO(vitalybuka):
51 // Clone, // Adds new field with value copied from another field.
Vitaly Buka0e17fd72016-11-18 18:02:4652};
53
Vitaly Bukab592ff02017-03-03 22:35:5254// Return random integer from [0, count)
Vitaly Bukaf62fe472017-03-02 07:05:1555size_t GetRandomIndex(RandomEngine* random, size_t count) {
Vitaly Bukab592ff02017-03-03 22:35:5256 assert(count > 0);
57 if (count == 1) return 0;
58 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
59}
60
Vitaly Buka4af611d2016-12-04 02:57:3261// Flips random bit in the buffer.
Vitaly Bukaf62fe472017-03-02 07:05:1562void FlipBit(size_t size, uint8_t* bytes, RandomEngine* random) {
Vitaly Bukab592ff02017-03-03 22:35:5263 size_t bit = GetRandomIndex(random, size * 8);
Vitaly Buka4af611d2016-12-04 02:57:3264 bytes[bit / 8] ^= (1u << (bit % 8));
65}
Vitaly Buka781853c2016-11-22 07:09:3566
Vitaly Buka4af611d2016-12-04 02:57:3267// Flips random bit in the value.
68template <class T>
Vitaly Bukaf62fe472017-03-02 07:05:1569T FlipBit(T value, RandomEngine* random) {
Vitaly Buka4af611d2016-12-04 02:57:3270 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
71 return value;
72}
Vitaly Buka781853c2016-11-22 07:09:3573
Vitaly Bukabeb90802017-02-28 23:28:1074// Return true with probability about 1-of-n.
Vitaly Bukaf62fe472017-03-02 07:05:1575bool GetRandomBool(RandomEngine* random, size_t n = 2) {
Vitaly Bukabeb90802017-02-28 23:28:1076 return GetRandomIndex(random, n) == 0;
77}
78
Vitaly Buka28ca0ee2017-03-05 05:35:4279bool IsProto3SimpleField(const FieldDescriptor& field) {
80 assert(field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
81 field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2);
82 return field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
83 field.cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
84 !field.containing_oneof() && !field.is_repeated();
85}
86
Vitaly Bukad4ab1e72017-03-04 07:51:1987struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
Vitaly Buka91ad7b02016-12-12 23:41:4188 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:1989 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:4190 T value;
91 field.GetDefault(&value);
92 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:3293 }
Vitaly Buka91ad7b02016-12-12 23:41:4194};
Vitaly Bukabec52222016-12-09 22:29:3295
Vitaly Bukad4ab1e72017-03-04 07:51:1996struct DeleteField : public FieldFunction<DeleteField> {
Vitaly Buka91ad7b02016-12-12 23:41:4197 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:1998 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:4199 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:32100 }
Vitaly Bukabec52222016-12-09 22:29:32101};
102
Vitaly Bukad4ab1e72017-03-04 07:51:19103struct CopyField : public FieldFunction<CopyField> {
Vitaly Bukaa3e59c72016-12-07 00:53:56104 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19105 void ForType(const ConstFieldInstance& source,
106 const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:56107 T value;
108 source.Load(&value);
109 field.Store(value);
110 }
Vitaly Bukaa3e59c72016-12-07 00:53:56111};
112
Vitaly Bukad4ab1e72017-03-04 07:51:19113struct AppendField : public FieldFunction<AppendField> {
Vitaly Bukaadfc27c2017-02-27 06:36:36114 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19115 void ForType(const ConstFieldInstance& source,
116 const FieldInstance& field) const {
Vitaly Bukaadfc27c2017-02-27 06:36:36117 T value;
118 source.Load(&value);
119 field.Create(value);
120 }
Vitaly Bukaadfc27c2017-02-27 06:36:36121};
122
Vitaly Buka2792ed72019-01-23 19:04:24123class CanCopyAndDifferentField
124 : public FieldFunction<CanCopyAndDifferentField, bool> {
Vitaly Buka4782c142017-03-04 08:12:32125 public:
126 template <class T>
Vitaly Buka2792ed72019-01-23 19:04:24127 bool ForType(const ConstFieldInstance& src,
128 const ConstFieldInstance& dst) const {
129 T s;
130 src.Load(&s);
131 if (!dst.CanStore(s)) return false;
132 T d;
133 dst.Load(&d);
134 return !IsEqual(s, d);
Vitaly Buka4782c142017-03-04 08:12:32135 }
136
137 private:
138 bool IsEqual(const ConstFieldInstance::Enum& a,
139 const ConstFieldInstance::Enum& b) const {
140 assert(a.count == b.count);
141 return a.index == b.index;
142 }
143
144 bool IsEqual(const std::unique_ptr<protobuf::Message>& a,
145 const std::unique_ptr<protobuf::Message>& b) const {
146 return MessageDifferencer::Equals(*a, *b);
147 }
148
149 template <class T>
150 bool IsEqual(const T& a, const T& b) const {
151 return a == b;
152 }
153};
154
Vitaly Buka4af611d2016-12-04 02:57:32155// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35156class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17157 public:
Vitaly Buka329fa462017-03-15 23:52:17158 MutationSampler(bool keep_initialized, RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-04 02:57:32159 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka781853c2016-11-22 07:09:35160 Sample(message);
Vitaly Bukaf3383a92017-03-20 00:04:18161 assert(mutation() != Mutation::None ||
162 message->GetDescriptor()->field_count() == 0);
Vitaly Bukac9d22482016-11-21 21:29:17163 }
164
Vitaly Buka4af611d2016-12-04 02:57:32165 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32166 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32167
168 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09169 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32170
171 private:
Vitaly Buka781853c2016-11-22 07:09:35172 void Sample(Message* message) {
173 const Descriptor* descriptor = message->GetDescriptor();
174 const Reflection* reflection = message->GetReflection();
175
176 int field_count = descriptor->field_count();
177 for (int i = 0; i < field_count; ++i) {
178 const FieldDescriptor* field = descriptor->field(i);
179 if (const OneofDescriptor* oneof = field->containing_oneof()) {
180 // Handle entire oneof group on the first field.
181 if (field->index_in_oneof() == 0) {
Vitaly Buka2f660a52017-03-04 03:46:14182 assert(oneof->field_count());
183 const FieldDescriptor* current_field =
184 reflection->GetOneofFieldDescriptor(*message, oneof);
185 for (;;) {
186 const FieldDescriptor* add_field =
187 oneof->field(GetRandomIndex(random_, oneof->field_count()));
188 if (add_field != current_field) {
Vitaly Buka329fa462017-03-15 23:52:17189 sampler_.Try(kDefaultMutateWeight,
190 {{message, add_field}, Mutation::Add});
Vitaly Buka2f660a52017-03-04 03:46:14191 break;
192 }
193 if (oneof->field_count() < 2) break;
194 }
195 if (current_field) {
Vitaly Buka28ca0ee2017-03-05 05:35:42196 if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka329fa462017-03-15 23:52:17197 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14198 {{message, current_field}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42199 }
Vitaly Buka329fa462017-03-15 23:52:17200 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14201 {{message, current_field}, Mutation::Delete});
Vitaly Buka329fa462017-03-15 23:52:17202 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka2f660a52017-03-04 03:46:14203 {{message, current_field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35204 }
205 }
206 } else {
207 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32208 int field_size = reflection->FieldSize(*message, field);
Vitaly Buka329fa462017-03-15 23:52:17209 sampler_.Try(
210 kDefaultMutateWeight,
211 {{message, field, GetRandomIndex(random_, field_size + 1)},
212 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35213
Vitaly Bukabec52222016-12-09 22:29:32214 if (field_size) {
215 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka28ca0ee2017-03-05 05:35:42216 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka329fa462017-03-15 23:52:17217 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32218 {{message, field, random_index}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-05 05:35:42219 }
Vitaly Buka329fa462017-03-15 23:52:17220 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32221 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka329fa462017-03-15 23:52:17222 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukaa3e59c72016-12-07 00:53:56223 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35224 }
225 } else {
Vitaly Buka28ca0ee2017-03-05 05:35:42226 if (reflection->HasField(*message, field) ||
227 IsProto3SimpleField(*field)) {
Vitaly Buka67387f72019-09-01 02:34:10228 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka329fa462017-03-15 23:52:17229 sampler_.Try(kDefaultMutateWeight,
230 {{message, field}, Mutation::Mutate});
Vitaly Buka67387f72019-09-01 02:34:10231 }
Vitaly Buka28ca0ee2017-03-05 05:35:42232 if (!IsProto3SimpleField(*field) &&
233 (!field->is_required() || !keep_initialized_)) {
Vitaly Buka329fa462017-03-15 23:52:17234 sampler_.Try(kDefaultMutateWeight,
Vitaly Bukabec52222016-12-09 22:29:32235 {{message, field}, Mutation::Delete});
Vitaly Buka28ca0ee2017-03-05 05:35:42236 }
Vitaly Buka329fa462017-03-15 23:52:17237 sampler_.Try(kDefaultMutateWeight,
Vitaly Buka72019dc2016-12-15 03:17:24238 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35239 } else {
Vitaly Buka329fa462017-03-15 23:52:17240 sampler_.Try(kDefaultMutateWeight,
241 {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35242 }
243 }
244 }
245
246 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
247 if (field->is_repeated()) {
248 const int field_size = reflection->FieldSize(*message, field);
249 for (int j = 0; j < field_size; ++j)
250 Sample(reflection->MutableRepeatedMessage(message, field, j));
251 } else if (reflection->HasField(*message, field)) {
252 Sample(reflection->MutableMessage(message, field));
253 }
254 }
255 }
256 }
257
Vitaly Buka781853c2016-11-22 07:09:35258 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32259
Vitaly Bukaf62fe472017-03-02 07:05:15260 RandomEngine* random_;
Vitaly Buka4af611d2016-12-04 02:57:32261
262 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41263 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32264 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41265
Vitaly Bukabec52222016-12-09 22:29:32266 FieldInstance field;
267 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32268 };
Vitaly Bukaf62fe472017-03-02 07:05:15269 WeightedReservoirSampler<Result, RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17270};
271
Vitaly Bukaa3e59c72016-12-07 00:53:56272// Selects random field of compatible type to use for clone mutations.
273class DataSourceSampler {
274 public:
Vitaly Bukaf62fe472017-03-02 07:05:15275 DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
Vitaly Buka0f63f912020-01-24 23:02:45276 const Message& message)
Vitaly Bukaa3e59c72016-12-07 00:53:56277 : match_(match), random_(random), sampler_(random) {
278 Sample(message);
279 }
280
281 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30282 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24283 assert(!IsEmpty());
284 return sampler_.selected();
285 }
286
287 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56288
289 private:
Vitaly Buka0f63f912020-01-24 23:02:45290 void Sample(const Message& message) {
291 const Descriptor* descriptor = message.GetDescriptor();
292 const Reflection* reflection = message.GetReflection();
Vitaly Bukaa3e59c72016-12-07 00:53:56293
294 int field_count = descriptor->field_count();
295 for (int i = 0; i < field_count; ++i) {
296 const FieldDescriptor* field = descriptor->field(i);
297 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
298 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45299 const int field_size = reflection->FieldSize(message, field);
Vitaly Bukaa3e59c72016-12-07 00:53:56300 for (int j = 0; j < field_size; ++j) {
Vitaly Buka0f63f912020-01-24 23:02:45301 Sample(reflection->GetRepeatedMessage(message, field, j));
Vitaly Bukaa3e59c72016-12-07 00:53:56302 }
Vitaly Buka0f63f912020-01-24 23:02:45303 } else if (reflection->HasField(message, field)) {
304 Sample(reflection->GetMessage(message, field));
Vitaly Bukaa3e59c72016-12-07 00:53:56305 }
306 }
307
308 if (field->cpp_type() != match_.cpp_type()) continue;
309 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
310 if (field->enum_type() != match_.enum_type()) continue;
311 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
312 if (field->message_type() != match_.message_type()) continue;
313 }
314
Vitaly Bukaa3e59c72016-12-07 00:53:56315 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45316 if (int field_size = reflection->FieldSize(message, field)) {
317 ConstFieldInstance source(&message, field,
Vitaly Buka4782c142017-03-04 08:12:32318 GetRandomIndex(random_, field_size));
Vitaly Buka2792ed72019-01-23 19:04:24319 if (CanCopyAndDifferentField()(source, match_))
Vitaly Buka4782c142017-03-04 08:12:32320 sampler_.Try(field_size, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56321 }
322 } else {
Vitaly Buka0f63f912020-01-24 23:02:45323 if (reflection->HasField(message, field)) {
324 ConstFieldInstance source(&message, field);
Vitaly Buka2792ed72019-01-23 19:04:24325 if (CanCopyAndDifferentField()(source, match_))
326 sampler_.Try(1, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56327 }
328 }
329 }
330 }
331
Vitaly Buka88712862017-02-27 06:21:30332 ConstFieldInstance match_;
Vitaly Bukaf62fe472017-03-02 07:05:15333 RandomEngine* random_;
Vitaly Bukaa3e59c72016-12-07 00:53:56334
Vitaly Bukaf62fe472017-03-02 07:05:15335 WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56336};
337
Vitaly Buka0e17fd72016-11-18 18:02:46338} // namespace
339
Vitaly Buka5d013202017-02-25 00:50:11340class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09341 public:
Vitaly Buka0e9439f2017-03-16 00:51:57342 FieldMutator(size_t size_increase_hint, bool enforce_changes,
Vitaly Buka0f63f912020-01-24 23:02:45343 bool enforce_utf8_strings, const protobuf::Message& source,
344 Mutator* mutator)
Vitaly Buka0e9439f2017-03-16 00:51:57345 : size_increase_hint_(size_increase_hint),
346 enforce_changes_(enforce_changes),
Vitaly Bukaaf8136f2017-06-09 23:40:12347 enforce_utf8_strings_(enforce_utf8_strings),
Vitaly Buka0f63f912020-01-24 23:02:45348 source_(source),
Vitaly Buka0e9439f2017-03-16 00:51:57349 mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41350
Vitaly Buka796b1122017-03-03 22:42:02351 void Mutate(int32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14352 RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02353 }
Vitaly Buka91ad7b02016-12-12 23:41:41354
Vitaly Buka796b1122017-03-03 22:42:02355 void Mutate(int64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14356 RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02357 }
Vitaly Buka91ad7b02016-12-12 23:41:41358
359 void Mutate(uint32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14360 RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41361 }
362
363 void Mutate(uint64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14364 RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41365 }
366
Vitaly Buka796b1122017-03-03 22:42:02367 void Mutate(float* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14368 RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02369 }
Vitaly Buka91ad7b02016-12-12 23:41:41370
Vitaly Buka796b1122017-03-03 22:42:02371 void Mutate(double* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14372 RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02373 }
Vitaly Buka91ad7b02016-12-12 23:41:41374
Vitaly Buka796b1122017-03-03 22:42:02375 void Mutate(bool* value) const {
Vitaly Bukad7f943f2019-01-31 22:05:33376 RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02377 }
Vitaly Buka91ad7b02016-12-12 23:41:41378
379 void Mutate(FieldInstance::Enum* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14380 RepeatMutate(&value->index,
Vitaly Bukad7f943f2019-01-31 22:05:33381 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count));
Vitaly Buka91ad7b02016-12-12 23:41:41382 assert(value->index < value->count);
383 }
384
385 void Mutate(std::string* value) const {
Vitaly Bukaaf8136f2017-06-09 23:40:12386 if (enforce_utf8_strings_) {
387 RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1,
388 size_increase_hint_));
389 } else {
390 RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
391 size_increase_hint_));
392 }
Vitaly Buka91ad7b02016-12-12 23:41:41393 }
394
Vitaly Bukab2c4fb52017-03-16 18:50:40395 void Mutate(std::unique_ptr<Message>* message) const {
396 assert(!enforce_changes_);
397 assert(*message);
Vitaly Bukad7f943f2019-01-31 22:05:33398 if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_))
399 return;
Vitaly Buka0f63f912020-01-24 23:02:45400 mutator_->MutateImpl(source_, message->get(), size_increase_hint_);
Vitaly Bukab2c4fb52017-03-16 18:50:40401 }
Vitaly Buka432b5452016-12-09 22:42:09402
Vitaly Buka5d013202017-02-25 00:50:11403 private:
Vitaly Buka796b1122017-03-03 22:42:02404 template <class T, class F>
Vitaly Bukad7f943f2019-01-31 22:05:33405 void RepeatMutate(T* value, F mutate) const {
Vitaly Buka0e9439f2017-03-16 00:51:57406 if (!enforce_changes_ &&
Vitaly Bukad7f943f2019-01-31 22:05:33407 GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) {
Vitaly Buka0e9439f2017-03-16 00:51:57408 return;
Vitaly Bukab2c4fb52017-03-16 18:50:40409 }
Vitaly Buka796b1122017-03-03 22:42:02410 T tmp = *value;
411 for (int i = 0; i < 10; ++i) {
412 *value = mutate(*value);
Vitaly Buka0e9439f2017-03-16 00:51:57413 if (!enforce_changes_ || *value != tmp) return;
Vitaly Buka796b1122017-03-03 22:42:02414 }
415 }
416
Vitaly Buka5d013202017-02-25 00:50:11417 size_t size_increase_hint_;
Vitaly Buka0e9439f2017-03-16 00:51:57418 size_t enforce_changes_;
Vitaly Bukaaf8136f2017-06-09 23:40:12419 bool enforce_utf8_strings_;
Vitaly Buka0f63f912020-01-24 23:02:45420 const protobuf::Message& source_;
Vitaly Bukae79e0182017-03-02 00:02:14421 Mutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09422};
423
Vitaly Buka5d013202017-02-25 00:50:11424namespace {
425
Vitaly Bukad4ab1e72017-03-04 07:51:19426struct MutateField : public FieldFunction<MutateField> {
Vitaly Buka5d013202017-02-25 00:50:11427 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19428 void ForType(const FieldInstance& field, size_t size_increase_hint,
Vitaly Buka0f63f912020-01-24 23:02:45429 const protobuf::Message& source, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11430 T value;
431 field.Load(&value);
Vitaly Buka0f63f912020-01-24 23:02:45432 FieldMutator(size_increase_hint, true, field.EnforceUtf8(), source, mutator)
Vitaly Bukaaf8136f2017-06-09 23:40:12433 .Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11434 field.Store(value);
435 }
Vitaly Buka5d013202017-02-25 00:50:11436};
437
Vitaly Bukad4ab1e72017-03-04 07:51:19438struct CreateField : public FieldFunction<CreateField> {
Vitaly Buka5d013202017-02-25 00:50:11439 public:
Vitaly Buka5d013202017-02-25 00:50:11440 template <class T>
Vitaly Buka490b23a2017-03-13 06:47:58441 void ForType(const FieldInstance& field, size_t size_increase_hint,
Vitaly Buka0f63f912020-01-24 23:02:45442 const protobuf::Message& source, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11443 T value;
444 field.GetDefault(&value);
Vitaly Buka0e9439f2017-03-16 00:51:57445 FieldMutator field_mutator(size_increase_hint,
Vitaly Bukaaf8136f2017-06-09 23:40:12446 false /* defaults could be useful */,
Vitaly Buka0f63f912020-01-24 23:02:45447 field.EnforceUtf8(), source, mutator);
Vitaly Buka0e9439f2017-03-16 00:51:57448 field_mutator.Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11449 field.Create(value);
450 }
Vitaly Buka5d013202017-02-25 00:50:11451};
452
453} // namespace
454
Vitaly Buka379f5ab2019-08-31 23:11:59455void Mutator::Seed(uint32_t value) { random_.seed(value); }
Vitaly Buka432b5452016-12-09 22:42:09456
Vitaly Bukae79e0182017-03-02 00:02:14457void Mutator::Mutate(Message* message, size_t size_increase_hint) {
Vitaly Buka0f63f912020-01-24 23:02:45458 MutateImpl(*message, message, size_increase_hint);
Vitaly Buka0e17fd72016-11-18 18:02:46459
Vitaly Bukae4eae602017-09-29 00:28:12460 InitializeAndTrim(message, kMaxInitializeDepth);
Vitaly Buka9eaf0632020-01-16 01:30:20461 assert(IsInitialized(*message));
Vitaly Buka67387f72019-09-01 02:34:10462
Peter Foleyfe76ed62019-10-01 00:03:37463 if (!post_processors_.empty()) {
464 ApplyPostProcessing(message);
465 }
466}
467
468void Mutator::RegisterPostProcessor(const protobuf::Descriptor* desc,
469 PostProcess callback) {
470 post_processors_.emplace(desc, callback);
471}
472
473void Mutator::ApplyPostProcessing(Message* message) {
474 const Descriptor* descriptor = message->GetDescriptor();
475
Vitaly Bukaad520b32020-01-08 22:39:55476 auto range = post_processors_.equal_range(descriptor);
477 for (auto it = range.first; it != range.second; ++it)
Peter Foleyfe76ed62019-10-01 00:03:37478 it->second(message, random_());
Peter Foleyfe76ed62019-10-01 00:03:37479
480 // Now recursively apply custom mutators.
481 const Reflection* reflection = message->GetReflection();
482 for (int i = 0; i < descriptor->field_count(); i++) {
483 const FieldDescriptor* field = descriptor->field(i);
484 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
485 continue;
486 }
487 if (field->is_repeated()) {
488 const int field_size = reflection->FieldSize(*message, field);
489 for (int j = 0; j < field_size; ++j) {
490 Message* nested_message =
491 reflection->MutableRepeatedMessage(message, field, j);
492 ApplyPostProcessing(nested_message);
493 }
494 } else if (reflection->HasField(*message, field)) {
495 Message* nested_message = reflection->MutableMessage(message, field);
496 ApplyPostProcessing(nested_message);
497 }
498 }
Vitaly Buka00b61072016-10-19 23:22:51499}
500
Vitaly Buka0f63f912020-01-24 23:02:45501void Mutator::MutateImpl(const Message& source, Message* message,
502 size_t size_increase_hint) {
Vitaly Buka3183b0d2019-09-06 22:11:10503 for (;;) {
504 MutationSampler mutation(keep_initialized_, &random_, message);
505 switch (mutation.mutation()) {
506 case Mutation::None:
507 return;
508 case Mutation::Add:
Vitaly Buka0f63f912020-01-24 23:02:45509 CreateField()(mutation.field(), size_increase_hint / 2, source, this);
Vitaly Buka3183b0d2019-09-06 22:11:10510 return;
511 case Mutation::Mutate:
Vitaly Buka0f63f912020-01-24 23:02:45512 MutateField()(mutation.field(), size_increase_hint / 2, source, this);
Vitaly Buka3183b0d2019-09-06 22:11:10513 return;
514 case Mutation::Delete:
515 DeleteField()(mutation.field());
516 return;
517 case Mutation::Copy: {
Vitaly Buka0f63f912020-01-24 23:02:45518 DataSourceSampler source_sampler(mutation.field(), &random_, source);
519 if (source_sampler.IsEmpty()) break;
520 CopyField()(source_sampler.field(), mutation.field());
Vitaly Buka3183b0d2019-09-06 22:11:10521 return;
522 }
523 default:
524 assert(false && "unexpected mutation");
525 return;
526 }
527 }
528}
529
Vitaly Bukae79e0182017-03-02 00:02:14530void Mutator::CrossOver(const protobuf::Message& message1,
531 protobuf::Message* message2) {
Vitaly Buka142e08b2017-03-06 00:26:15532 // CrossOver can produce result which still equals to inputs. So we backup
533 // message2 to later comparison. message1 is already constant.
534 std::unique_ptr<protobuf::Message> message2_copy(message2->New());
535 message2_copy->CopyFrom(*message2);
536
Vitaly Bukaadfc27c2017-02-27 06:36:36537 CrossOverImpl(message1, message2);
538
Vitaly Bukae4eae602017-09-29 00:28:12539 InitializeAndTrim(message2, kMaxInitializeDepth);
Vitaly Buka9eaf0632020-01-16 01:30:20540 assert(IsInitialized(*message2));
Vitaly Buka142e08b2017-03-06 00:26:15541
Vitaly Bukadd89da92019-10-08 17:08:02542 if (!post_processors_.empty()) {
543 ApplyPostProcessing(message2);
544 }
Vitaly Buka67387f72019-09-01 02:34:10545
Vitaly Buka2d609df2017-03-07 07:29:47546 // Can't call mutate from crossover because of a bug in libFuzzer.
Vitaly Buka2d609df2017-03-07 07:29:47547 // if (MessageDifferencer::Equals(*message2_copy, *message2) ||
548 // MessageDifferencer::Equals(message1, *message2)) {
549 // Mutate(message2, 0);
550 // }
Vitaly Bukaadfc27c2017-02-27 06:36:36551}
552
Vitaly Bukae79e0182017-03-02 00:02:14553void Mutator::CrossOverImpl(const protobuf::Message& message1,
554 protobuf::Message* message2) {
Vitaly Bukaadfc27c2017-02-27 06:36:36555 const Descriptor* descriptor = message2->GetDescriptor();
556 const Reflection* reflection = message2->GetReflection();
557 assert(message1.GetDescriptor() == descriptor);
558 assert(message1.GetReflection() == reflection);
559
560 for (int i = 0; i < descriptor->field_count(); ++i) {
561 const FieldDescriptor* field = descriptor->field(i);
562
563 if (field->is_repeated()) {
564 const int field_size1 = reflection->FieldSize(message1, field);
565 int field_size2 = reflection->FieldSize(*message2, field);
566 for (int j = 0; j < field_size1; ++j) {
567 ConstFieldInstance source(&message1, field, j);
568 FieldInstance destination(message2, field, field_size2++);
Vitaly Bukad4ab1e72017-03-04 07:51:19569 AppendField()(source, destination);
Vitaly Bukaadfc27c2017-02-27 06:36:36570 }
571
572 assert(field_size2 == reflection->FieldSize(*message2, field));
573
574 // Shuffle
575 for (int j = 0; j < field_size2; ++j) {
Vitaly Buka379f5ab2019-08-31 23:11:59576 if (int k = GetRandomIndex(&random_, field_size2 - j)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36577 reflection->SwapElements(message2, field, j, j + k);
578 }
579 }
580
Vitaly Buka379f5ab2019-08-31 23:11:59581 int keep = GetRandomIndex(&random_, field_size2 + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36582
583 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
584 int remove = field_size2 - keep;
585 // Cross some message to keep with messages to remove.
Vitaly Buka379f5ab2019-08-31 23:11:59586 int cross = GetRandomIndex(&random_, std::min(keep, remove) + 1);
Vitaly Bukaadfc27c2017-02-27 06:36:36587 for (int j = 0; j < cross; ++j) {
Vitaly Buka379f5ab2019-08-31 23:11:59588 int k = GetRandomIndex(&random_, keep);
589 int r = keep + GetRandomIndex(&random_, remove);
Vitaly Bukaadfc27c2017-02-27 06:36:36590 assert(k != r);
591 CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
592 reflection->MutableRepeatedMessage(message2, field, k));
593 }
594 }
595
596 for (int j = keep; j < field_size2; ++j)
597 reflection->RemoveLast(message2, field);
598 assert(keep == reflection->FieldSize(*message2, field));
599
600 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
601 if (!reflection->HasField(message1, field)) {
Vitaly Buka379f5ab2019-08-31 23:11:59602 if (GetRandomBool(&random_))
Vitaly Bukad4ab1e72017-03-04 07:51:19603 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36604 } else if (!reflection->HasField(*message2, field)) {
Vitaly Buka379f5ab2019-08-31 23:11:59605 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36606 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19607 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36608 }
609 } else {
610 CrossOverImpl(reflection->GetMessage(message1, field),
611 reflection->MutableMessage(message2, field));
612 }
613 } else {
Vitaly Buka379f5ab2019-08-31 23:11:59614 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36615 if (reflection->HasField(message1, field)) {
616 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-04 07:51:19617 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36618 } else {
Vitaly Bukad4ab1e72017-03-04 07:51:19619 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-27 06:36:36620 }
621 }
622 }
623 }
624}
625
Vitaly Bukae4eae602017-09-29 00:28:12626void Mutator::InitializeAndTrim(Message* message, int max_depth) {
Vitaly Buka13245af2016-11-18 21:20:12627 const Descriptor* descriptor = message->GetDescriptor();
628 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12629 for (int i = 0; i < descriptor->field_count(); ++i) {
630 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka4200a1e2019-07-29 22:19:59631 if (keep_initialized_ &&
632 (field->is_required() || descriptor->options().map_entry()) &&
633 !reflection->HasField(*message, field)) {
Vitaly Bukad4ab1e72017-03-04 07:51:19634 CreateDefaultField()(FieldInstance(message, field));
Vitaly Buka4200a1e2019-07-29 22:19:59635 }
Vitaly Buka13245af2016-11-18 21:20:12636
Vitaly Bukae4eae602017-09-29 00:28:12637 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
638 if (max_depth <= 0 && !field->is_required()) {
639 // Clear deep optional fields to avoid stack overflow.
640 reflection->ClearField(message, field);
641 if (field->is_repeated())
642 assert(!reflection->FieldSize(*message, field));
643 else
644 assert(!reflection->HasField(*message, field));
645 continue;
646 }
647
Vitaly Buka2cfe02b2016-11-19 00:34:09648 if (field->is_repeated()) {
649 const int field_size = reflection->FieldSize(*message, field);
650 for (int j = 0; j < field_size; ++j) {
651 Message* nested_message =
652 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Bukae4eae602017-09-29 00:28:12653 InitializeAndTrim(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09654 }
655 } else if (reflection->HasField(*message, field)) {
656 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Bukae4eae602017-09-29 00:28:12657 InitializeAndTrim(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12658 }
659 }
660 }
661}
Vitaly Buka4af611d2016-12-04 02:57:32662
Vitaly Buka379f5ab2019-08-31 23:11:59663int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14664
Vitaly Buka379f5ab2019-08-31 23:11:59665int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14666
667uint32_t Mutator::MutateUInt32(uint32_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59668 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32669}
670
Vitaly Bukae79e0182017-03-02 00:02:14671uint64_t Mutator::MutateUInt64(uint64_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59672 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32673}
674
Vitaly Buka379f5ab2019-08-31 23:11:59675float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32676
Vitaly Buka379f5ab2019-08-31 23:11:59677double Mutator::MutateDouble(double value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32678
Vitaly Bukae79e0182017-03-02 00:02:14679bool Mutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-04 02:57:32680
Vitaly Bukae79e0182017-03-02 00:02:14681size_t Mutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukaee1c76a2017-03-15 17:48:53682 if (item_count <= 1) return 0;
Vitaly Buka379f5ab2019-08-31 23:11:59683 return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-04 02:57:32684}
685
Vitaly Bukae79e0182017-03-02 00:02:14686std::string Mutator::MutateString(const std::string& value,
687 size_t size_increase_hint) {
Vitaly Buka4af611d2016-12-04 02:57:32688 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11689
Vitaly Buka379f5ab2019-08-31 23:11:59690 while (!result.empty() && GetRandomBool(&random_)) {
691 result.erase(GetRandomIndex(&random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09692 }
693
Vitaly Buka379f5ab2019-08-31 23:11:59694 while (result.size() < size_increase_hint && GetRandomBool(&random_)) {
695 size_t index = GetRandomIndex(&random_, result.size() + 1);
696 result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09697 }
698
Vitaly Bukac020de12017-03-04 03:36:23699 if (result != value) return result;
700
701 if (result.empty()) {
Vitaly Buka379f5ab2019-08-31 23:11:59702 result.push_back(GetRandomIndex(&random_, 1 << 8));
Vitaly Bukac020de12017-03-04 03:36:23703 return result;
704 }
705
Vitaly Buka4af611d2016-12-04 02:57:32706 if (!result.empty())
Vitaly Buka379f5ab2019-08-31 23:11:59707 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
Vitaly Buka4af611d2016-12-04 02:57:32708 return result;
709}
Vitaly Buka432b5452016-12-09 22:42:09710
Vitaly Bukaaf8136f2017-06-09 23:40:12711std::string Mutator::MutateUtf8String(const std::string& value,
712 size_t size_increase_hint) {
713 std::string str = MutateString(value, size_increase_hint);
Vitaly Buka379f5ab2019-08-31 23:11:59714 FixUtf8String(&str, &random_);
Vitaly Bukaaf8136f2017-06-09 23:40:12715 return str;
716}
717
Vitaly Buka9eaf0632020-01-16 01:30:20718bool Mutator::IsInitialized(const Message& message) const {
719 if (!keep_initialized_ || message.IsInitialized()) return true;
720 std::cerr << "Uninitialized: " << message.DebugString() << "\n";
721 return false;
722}
723
Vitaly Buka432b5452016-12-09 22:42:09724} // namespace protobuf_mutator