blob: 0243d03df6001f150a26b7972ba06a1a2b3c9825 [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 Bukac1839912020-01-27 06:32:5718#include <bitset>
Vitaly Buka0e17fd72016-11-18 18:02:4619#include <map>
Vitaly Buka781853c2016-11-22 07:09:3520#include <random>
Vitaly Buka0e17fd72016-11-18 18:02:4621#include <string>
Allen-Webbc4fa5912018-09-07 22:53:3022#include <vector>
Vitaly Buka00b61072016-10-19 23:22:5123
Vitaly Buka9dd2f8e2017-01-13 08:48:3124#include "src/field_instance.h"
Vitaly Bukaaf8136f2017-06-09 23:40:1225#include "src/utf8_fix.h"
Vitaly Buka9dd2f8e2017-01-13 08:48:3126#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 23:22:5127
Vitaly Bukaf86815c2017-02-27 22:19:1928namespace protobuf_mutator {
29
Vitaly Buka6c6dbbe2017-02-22 21:58:2430using protobuf::Descriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2431using protobuf::FieldDescriptor;
Vitaly Buka796b1122017-03-03 22:42:0232using protobuf::FileDescriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2433using protobuf::Message;
34using protobuf::OneofDescriptor;
35using protobuf::Reflection;
Vitaly Buka4782c142017-03-04 08:12:3236using protobuf::util::MessageDifferencer;
Vitaly Buka796b1122017-03-03 22:42:0237using std::placeholders::_1;
Vitaly Buka0e17fd72016-11-18 18:02:4638
39namespace {
40
Vitaly Bukae4eae602017-09-29 00:28:1241const int kMaxInitializeDepth = 200;
Vitaly Buka329fa462017-03-15 23:52:1742const uint64_t kDefaultMutateWeight = 1000000;
Vitaly Buka0e17fd72016-11-18 18:02:4643
Vitaly Bukac1839912020-01-27 06:32:5744enum class Mutation : uint8_t {
Vitaly Buka30de3092016-11-18 19:39:0745 None,
Vitaly Buka4af611d2016-12-04 02:57:3246 Add, // Adds new field with default value.
47 Mutate, // Mutates field contents.
48 Delete, // Deletes field.
Vitaly Bukaa3e59c72016-12-07 00:53:5649 Copy, // Copy values copied from another field.
Vitaly Buka5635a7a2020-01-26 09:52:4050 Clone, // Create new field with value copied from another.
Vitaly Bukac1839912020-01-27 06:32:5751
52 Last = Clone,
Vitaly Buka0e17fd72016-11-18 18:02:4653};
54
Vitaly Bukac1839912020-01-27 06:32:5755using MutationBitset = std::bitset<static_cast<size_t>(Mutation::Last)>;
56
Vitaly Bukaf62086c2020-01-29 09:11:2357using Messages = std::vector<Message*>;
58using ConstMessages = std::vector<const Message*>;
59
Vitaly Bukab592ff02017-03-03 22:35:5260// Return random integer from [0, count)
Vitaly Bukaf62fe472017-03-02 07:05:1561size_t GetRandomIndex(RandomEngine* random, size_t count) {
Vitaly Bukab592ff02017-03-03 22:35:5262 assert(count > 0);
63 if (count == 1) return 0;
64 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
65}
66
Vitaly Buka4af611d2016-12-04 02:57:3267// Flips random bit in the buffer.
Vitaly Bukaf62fe472017-03-02 07:05:1568void FlipBit(size_t size, uint8_t* bytes, RandomEngine* random) {
Vitaly Bukab592ff02017-03-03 22:35:5269 size_t bit = GetRandomIndex(random, size * 8);
Vitaly Buka4af611d2016-12-04 02:57:3270 bytes[bit / 8] ^= (1u << (bit % 8));
71}
Vitaly Buka781853c2016-11-22 07:09:3572
Vitaly Buka4af611d2016-12-04 02:57:3273// Flips random bit in the value.
74template <class T>
Vitaly Bukaf62fe472017-03-02 07:05:1575T FlipBit(T value, RandomEngine* random) {
Vitaly Buka4af611d2016-12-04 02:57:3276 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
77 return value;
78}
Vitaly Buka781853c2016-11-22 07:09:3579
Vitaly Bukabeb90802017-02-28 23:28:1080// Return true with probability about 1-of-n.
Vitaly Bukaf62fe472017-03-02 07:05:1581bool GetRandomBool(RandomEngine* random, size_t n = 2) {
Vitaly Bukabeb90802017-02-28 23:28:1082 return GetRandomIndex(random, n) == 0;
83}
84
Vitaly Buka28ca0ee2017-03-05 05:35:4285bool IsProto3SimpleField(const FieldDescriptor& field) {
86 assert(field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
87 field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2);
88 return field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
89 field.cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
90 !field.containing_oneof() && !field.is_repeated();
91}
92
Vitaly Bukad4ab1e72017-03-04 07:51:1993struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
Vitaly Buka91ad7b02016-12-12 23:41:4194 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:1995 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:4196 T value;
97 field.GetDefault(&value);
98 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:3299 }
Vitaly Buka91ad7b02016-12-12 23:41:41100};
Vitaly Bukabec52222016-12-09 22:29:32101
Vitaly Bukad4ab1e72017-03-04 07:51:19102struct DeleteField : public FieldFunction<DeleteField> {
Vitaly Buka91ad7b02016-12-12 23:41:41103 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19104 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:41105 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:32106 }
Vitaly Bukabec52222016-12-09 22:29:32107};
108
Vitaly Bukad4ab1e72017-03-04 07:51:19109struct CopyField : public FieldFunction<CopyField> {
Vitaly Bukaa3e59c72016-12-07 00:53:56110 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19111 void ForType(const ConstFieldInstance& source,
112 const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:56113 T value;
114 source.Load(&value);
115 field.Store(value);
116 }
Vitaly Bukaa3e59c72016-12-07 00:53:56117};
118
Vitaly Bukad4ab1e72017-03-04 07:51:19119struct AppendField : public FieldFunction<AppendField> {
Vitaly Bukaadfc27c2017-02-27 06:36:36120 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19121 void ForType(const ConstFieldInstance& source,
122 const FieldInstance& field) const {
Vitaly Bukaadfc27c2017-02-27 06:36:36123 T value;
124 source.Load(&value);
125 field.Create(value);
126 }
Vitaly Bukaadfc27c2017-02-27 06:36:36127};
128
Vitaly Buka2792ed72019-01-23 19:04:24129class CanCopyAndDifferentField
130 : public FieldFunction<CanCopyAndDifferentField, bool> {
Vitaly Buka4782c142017-03-04 08:12:32131 public:
132 template <class T>
Vitaly Buka5cd166e2020-01-26 06:33:05133 bool ForType(const ConstFieldInstance& src, const ConstFieldInstance& dst,
134 int size_increase_hint) const {
Vitaly Buka2792ed72019-01-23 19:04:24135 T s;
136 src.Load(&s);
137 if (!dst.CanStore(s)) return false;
138 T d;
139 dst.Load(&d);
Vitaly Buka5cd166e2020-01-26 06:33:05140 return SizeDiff(s, d) <= size_increase_hint && !IsEqual(s, d);
Vitaly Buka4782c142017-03-04 08:12:32141 }
142
143 private:
144 bool IsEqual(const ConstFieldInstance::Enum& a,
145 const ConstFieldInstance::Enum& b) const {
146 assert(a.count == b.count);
147 return a.index == b.index;
148 }
149
Vitaly Bukad3600272020-01-27 07:24:10150 bool IsEqual(const std::unique_ptr<Message>& a,
151 const std::unique_ptr<Message>& b) const {
Vitaly Buka4782c142017-03-04 08:12:32152 return MessageDifferencer::Equals(*a, *b);
153 }
154
155 template <class T>
156 bool IsEqual(const T& a, const T& b) const {
157 return a == b;
158 }
Vitaly Buka5cd166e2020-01-26 06:33:05159
Vitaly Bukad3600272020-01-27 07:24:10160 int64_t SizeDiff(const std::unique_ptr<Message>& src,
161 const std::unique_ptr<Message>& dst) const {
Vitaly Buka5cd166e2020-01-26 06:33:05162 return src->ByteSizeLong() - dst->ByteSizeLong();
163 }
164
165 int64_t SizeDiff(const std::string& src, const std::string& dst) const {
166 return src.size() - dst.size();
167 }
168
169 template <class T>
170 int64_t SizeDiff(const T&, const T&) const {
171 return 0;
172 }
Vitaly Buka4782c142017-03-04 08:12:32173};
174
Vitaly Buka4af611d2016-12-04 02:57:32175// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35176class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17177 public:
Vitaly Bukac1839912020-01-27 06:32:57178 MutationSampler(bool keep_initialized, MutationBitset allowed_mutations,
Vitaly Bukaf62086c2020-01-29 09:11:23179 RandomEngine* random)
Vitaly Buka4908d252020-01-25 03:10:34180 : keep_initialized_(keep_initialized),
Vitaly Bukac1839912020-01-27 06:32:57181 allowed_mutations_(allowed_mutations),
Vitaly Buka4908d252020-01-25 03:10:34182 random_(random),
Vitaly Bukaf62086c2020-01-29 09:11:23183 sampler_(random) {}
Vitaly Bukac9d22482016-11-21 21:29:17184
Vitaly Buka4af611d2016-12-04 02:57:32185 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32186 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32187
188 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09189 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32190
Vitaly Buka781853c2016-11-22 07:09:35191 void Sample(Message* message) {
Vitaly Bukaf62086c2020-01-29 09:11:23192 SampleImpl(message);
193 assert(mutation() != Mutation::None ||
194 !allowed_mutations_[static_cast<size_t>(Mutation::Mutate)] ||
195 message->GetDescriptor()->field_count() == 0);
196 }
197
198 private:
199 void SampleImpl(Message* message) {
Vitaly Buka781853c2016-11-22 07:09:35200 const Descriptor* descriptor = message->GetDescriptor();
201 const Reflection* reflection = message->GetReflection();
202
203 int field_count = descriptor->field_count();
204 for (int i = 0; i < field_count; ++i) {
205 const FieldDescriptor* field = descriptor->field(i);
206 if (const OneofDescriptor* oneof = field->containing_oneof()) {
207 // Handle entire oneof group on the first field.
208 if (field->index_in_oneof() == 0) {
Vitaly Buka2f660a52017-03-04 03:46:14209 assert(oneof->field_count());
210 const FieldDescriptor* current_field =
211 reflection->GetOneofFieldDescriptor(*message, oneof);
212 for (;;) {
213 const FieldDescriptor* add_field =
214 oneof->field(GetRandomIndex(random_, oneof->field_count()));
215 if (add_field != current_field) {
Vitaly Buka4908d252020-01-25 03:10:34216 Try({message, add_field}, Mutation::Add);
Vitaly Buka5635a7a2020-01-26 09:52:40217 Try({message, add_field}, Mutation::Clone);
Vitaly Buka2f660a52017-03-04 03:46:14218 break;
219 }
220 if (oneof->field_count() < 2) break;
221 }
222 if (current_field) {
Vitaly Buka4908d252020-01-25 03:10:34223 if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
224 Try({message, current_field}, Mutation::Mutate);
225 Try({message, current_field}, Mutation::Delete);
226 Try({message, current_field}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35227 }
228 }
229 } else {
230 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32231 int field_size = reflection->FieldSize(*message, field);
Vitaly Buka5635a7a2020-01-26 09:52:40232 size_t random_index = GetRandomIndex(random_, field_size + 1);
233 Try({message, field, random_index}, Mutation::Add);
234 Try({message, field, random_index}, Mutation::Clone);
Vitaly Buka781853c2016-11-22 07:09:35235
Vitaly Bukabec52222016-12-09 22:29:32236 if (field_size) {
237 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka4908d252020-01-25 03:10:34238 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
239 Try({message, field, random_index}, Mutation::Mutate);
240 Try({message, field, random_index}, Mutation::Delete);
241 Try({message, field, random_index}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35242 }
243 } else {
Vitaly Buka28ca0ee2017-03-05 05:35:42244 if (reflection->HasField(*message, field) ||
245 IsProto3SimpleField(*field)) {
Vitaly Buka4908d252020-01-25 03:10:34246 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
247 Try({message, field}, Mutation::Mutate);
Vitaly Buka28ca0ee2017-03-05 05:35:42248 if (!IsProto3SimpleField(*field) &&
249 (!field->is_required() || !keep_initialized_)) {
Vitaly Buka4908d252020-01-25 03:10:34250 Try({message, field}, Mutation::Delete);
Vitaly Buka28ca0ee2017-03-05 05:35:42251 }
Vitaly Buka4908d252020-01-25 03:10:34252 Try({message, field}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35253 } else {
Vitaly Buka4908d252020-01-25 03:10:34254 Try({message, field}, Mutation::Add);
Vitaly Buka5635a7a2020-01-26 09:52:40255 Try({message, field}, Mutation::Clone);
Vitaly Buka781853c2016-11-22 07:09:35256 }
257 }
258 }
259
260 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
261 if (field->is_repeated()) {
262 const int field_size = reflection->FieldSize(*message, field);
263 for (int j = 0; j < field_size; ++j)
Vitaly Bukaf62086c2020-01-29 09:11:23264 SampleImpl(reflection->MutableRepeatedMessage(message, field, j));
Vitaly Buka781853c2016-11-22 07:09:35265 } else if (reflection->HasField(*message, field)) {
Vitaly Bukaf62086c2020-01-29 09:11:23266 SampleImpl(reflection->MutableMessage(message, field));
Vitaly Buka781853c2016-11-22 07:09:35267 }
268 }
269 }
270 }
271
Vitaly Buka4908d252020-01-25 03:10:34272 void Try(const FieldInstance& field, Mutation mutation) {
273 assert(mutation != Mutation::None);
Vitaly Bukac1839912020-01-27 06:32:57274 if (!allowed_mutations_[static_cast<size_t>(mutation)]) return;
Vitaly Buka4908d252020-01-25 03:10:34275 sampler_.Try(kDefaultMutateWeight, {field, mutation});
276 }
277
Vitaly Buka781853c2016-11-22 07:09:35278 bool keep_initialized_ = false;
Vitaly Bukac1839912020-01-27 06:32:57279 MutationBitset allowed_mutations_;
Vitaly Buka4af611d2016-12-04 02:57:32280
Vitaly Bukaf62fe472017-03-02 07:05:15281 RandomEngine* random_;
Vitaly Buka4af611d2016-12-04 02:57:32282
283 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41284 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32285 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41286
Vitaly Bukabec52222016-12-09 22:29:32287 FieldInstance field;
288 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32289 };
Vitaly Bukaf62fe472017-03-02 07:05:15290 WeightedReservoirSampler<Result, RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17291};
292
Vitaly Bukaa3e59c72016-12-07 00:53:56293// Selects random field of compatible type to use for clone mutations.
294class DataSourceSampler {
295 public:
Vitaly Bukaf62fe472017-03-02 07:05:15296 DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
Vitaly Bukaf62086c2020-01-29 09:11:23297 int size_increase_hint)
Vitaly Buka5cd166e2020-01-26 06:33:05298 : match_(match),
299 random_(random),
300 size_increase_hint_(size_increase_hint),
Vitaly Bukaf62086c2020-01-29 09:11:23301 sampler_(random) {}
302
303 void Sample(const Message& message) { SampleImpl(message); }
Vitaly Bukaa3e59c72016-12-07 00:53:56304
305 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30306 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24307 assert(!IsEmpty());
308 return sampler_.selected();
309 }
310
311 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56312
313 private:
Vitaly Bukaf62086c2020-01-29 09:11:23314 void SampleImpl(const Message& message) {
Vitaly Buka0f63f912020-01-24 23:02:45315 const Descriptor* descriptor = message.GetDescriptor();
316 const Reflection* reflection = message.GetReflection();
Vitaly Bukaa3e59c72016-12-07 00:53:56317
318 int field_count = descriptor->field_count();
319 for (int i = 0; i < field_count; ++i) {
320 const FieldDescriptor* field = descriptor->field(i);
321 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
322 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45323 const int field_size = reflection->FieldSize(message, field);
Vitaly Bukaa3e59c72016-12-07 00:53:56324 for (int j = 0; j < field_size; ++j) {
Vitaly Bukaf62086c2020-01-29 09:11:23325 SampleImpl(reflection->GetRepeatedMessage(message, field, j));
Vitaly Bukaa3e59c72016-12-07 00:53:56326 }
Vitaly Buka0f63f912020-01-24 23:02:45327 } else if (reflection->HasField(message, field)) {
Vitaly Bukaf62086c2020-01-29 09:11:23328 SampleImpl(reflection->GetMessage(message, field));
Vitaly Bukaa3e59c72016-12-07 00:53:56329 }
330 }
331
332 if (field->cpp_type() != match_.cpp_type()) continue;
333 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
334 if (field->enum_type() != match_.enum_type()) continue;
335 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
336 if (field->message_type() != match_.message_type()) continue;
337 }
338
Vitaly Bukaa3e59c72016-12-07 00:53:56339 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45340 if (int field_size = reflection->FieldSize(message, field)) {
341 ConstFieldInstance source(&message, field,
Vitaly Buka4782c142017-03-04 08:12:32342 GetRandomIndex(random_, field_size));
Vitaly Buka5cd166e2020-01-26 06:33:05343 if (CanCopyAndDifferentField()(source, match_, size_increase_hint_))
Vitaly Buka4782c142017-03-04 08:12:32344 sampler_.Try(field_size, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56345 }
346 } else {
Vitaly Buka0f63f912020-01-24 23:02:45347 if (reflection->HasField(message, field)) {
348 ConstFieldInstance source(&message, field);
Vitaly Buka5cd166e2020-01-26 06:33:05349 if (CanCopyAndDifferentField()(source, match_, size_increase_hint_))
Vitaly Buka2792ed72019-01-23 19:04:24350 sampler_.Try(1, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56351 }
352 }
353 }
354 }
355
Vitaly Buka88712862017-02-27 06:21:30356 ConstFieldInstance match_;
Vitaly Bukaf62fe472017-03-02 07:05:15357 RandomEngine* random_;
Vitaly Buka5cd166e2020-01-26 06:33:05358 int size_increase_hint_;
Vitaly Bukaa3e59c72016-12-07 00:53:56359
Vitaly Bukaf62fe472017-03-02 07:05:15360 WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56361};
362
Vitaly Buka045acda2020-01-29 08:26:35363class PostProcessing {
364 public:
Vitaly Bukaf62086c2020-01-29 09:11:23365 using PostProcessors =
366 std::unordered_multimap<const Descriptor*, Mutator::PostProcess>;
Vitaly Buka045acda2020-01-29 08:26:35367
368 PostProcessing(bool keep_initialized, const PostProcessors& post_processors,
369 RandomEngine* random)
370 : keep_initialized_(keep_initialized),
371 post_processors_(post_processors),
372 random_(random) {}
373
374 void Run(Message* message, int max_depth) {
375 --max_depth;
376 const Descriptor* descriptor = message->GetDescriptor();
377
378 // Apply custom mutators in nested messages before packing any.
379 const Reflection* reflection = message->GetReflection();
380 for (int i = 0; i < descriptor->field_count(); i++) {
381 const FieldDescriptor* field = descriptor->field(i);
382 if (keep_initialized_ &&
383 (field->is_required() || descriptor->options().map_entry()) &&
384 !reflection->HasField(*message, field)) {
385 CreateDefaultField()(FieldInstance(message, field));
386 }
387
388 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
389
390 if (max_depth < 0 && !field->is_required()) {
391 // Clear deep optional fields to avoid stack overflow.
392 reflection->ClearField(message, field);
393 if (field->is_repeated())
394 assert(!reflection->FieldSize(*message, field));
395 else
396 assert(!reflection->HasField(*message, field));
397 continue;
398 }
399
400 if (field->is_repeated()) {
401 const int field_size = reflection->FieldSize(*message, field);
402 for (int j = 0; j < field_size; ++j) {
403 Message* nested_message =
404 reflection->MutableRepeatedMessage(message, field, j);
405 Run(nested_message, max_depth);
406 }
407 } else if (reflection->HasField(*message, field)) {
408 Message* nested_message = reflection->MutableMessage(message, field);
409 Run(nested_message, max_depth);
410 }
411 }
412
413 auto range = post_processors_.equal_range(descriptor);
414 for (auto it = range.first; it != range.second; ++it)
415 it->second(message, (*random_)());
416 }
417
418 private:
419 bool keep_initialized_;
420 const PostProcessors& post_processors_;
421 RandomEngine* random_;
422};
423
Vitaly Buka0e17fd72016-11-18 18:02:46424} // namespace
425
Vitaly Buka5d013202017-02-25 00:50:11426class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09427 public:
Vitaly Buka1c91e722020-01-26 05:56:22428 FieldMutator(int size_increase_hint, bool enforce_changes,
Vitaly Bukaf62086c2020-01-29 09:11:23429 bool enforce_utf8_strings, const ConstMessages& sources,
Vitaly Buka0f63f912020-01-24 23:02:45430 Mutator* mutator)
Vitaly Buka0e9439f2017-03-16 00:51:57431 : size_increase_hint_(size_increase_hint),
432 enforce_changes_(enforce_changes),
Vitaly Bukaaf8136f2017-06-09 23:40:12433 enforce_utf8_strings_(enforce_utf8_strings),
Vitaly Bukaf62086c2020-01-29 09:11:23434 sources_(sources),
Vitaly Buka0e9439f2017-03-16 00:51:57435 mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41436
Vitaly Buka796b1122017-03-03 22:42:02437 void Mutate(int32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14438 RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02439 }
Vitaly Buka91ad7b02016-12-12 23:41:41440
Vitaly Buka796b1122017-03-03 22:42:02441 void Mutate(int64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14442 RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02443 }
Vitaly Buka91ad7b02016-12-12 23:41:41444
445 void Mutate(uint32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14446 RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41447 }
448
449 void Mutate(uint64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14450 RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41451 }
452
Vitaly Buka796b1122017-03-03 22:42:02453 void Mutate(float* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14454 RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02455 }
Vitaly Buka91ad7b02016-12-12 23:41:41456
Vitaly Buka796b1122017-03-03 22:42:02457 void Mutate(double* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14458 RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02459 }
Vitaly Buka91ad7b02016-12-12 23:41:41460
Vitaly Buka796b1122017-03-03 22:42:02461 void Mutate(bool* value) const {
Vitaly Bukad7f943f2019-01-31 22:05:33462 RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02463 }
Vitaly Buka91ad7b02016-12-12 23:41:41464
465 void Mutate(FieldInstance::Enum* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14466 RepeatMutate(&value->index,
Vitaly Bukad7f943f2019-01-31 22:05:33467 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count));
Vitaly Buka91ad7b02016-12-12 23:41:41468 assert(value->index < value->count);
469 }
470
471 void Mutate(std::string* value) const {
Vitaly Bukaaf8136f2017-06-09 23:40:12472 if (enforce_utf8_strings_) {
473 RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1,
474 size_increase_hint_));
475 } else {
476 RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
477 size_increase_hint_));
478 }
Vitaly Buka91ad7b02016-12-12 23:41:41479 }
480
Vitaly Bukab2c4fb52017-03-16 18:50:40481 void Mutate(std::unique_ptr<Message>* message) const {
482 assert(!enforce_changes_);
483 assert(*message);
Vitaly Bukad7f943f2019-01-31 22:05:33484 if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_))
485 return;
Vitaly Bukaf62086c2020-01-29 09:11:23486 mutator_->MutateImpl(sources_, {message->get()}, false,
487 size_increase_hint_);
Vitaly Bukab2c4fb52017-03-16 18:50:40488 }
Vitaly Buka432b5452016-12-09 22:42:09489
Vitaly Buka5d013202017-02-25 00:50:11490 private:
Vitaly Buka796b1122017-03-03 22:42:02491 template <class T, class F>
Vitaly Bukad7f943f2019-01-31 22:05:33492 void RepeatMutate(T* value, F mutate) const {
Vitaly Buka0e9439f2017-03-16 00:51:57493 if (!enforce_changes_ &&
Vitaly Bukad7f943f2019-01-31 22:05:33494 GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) {
Vitaly Buka0e9439f2017-03-16 00:51:57495 return;
Vitaly Bukab2c4fb52017-03-16 18:50:40496 }
Vitaly Buka796b1122017-03-03 22:42:02497 T tmp = *value;
498 for (int i = 0; i < 10; ++i) {
499 *value = mutate(*value);
Vitaly Buka0e9439f2017-03-16 00:51:57500 if (!enforce_changes_ || *value != tmp) return;
Vitaly Buka796b1122017-03-03 22:42:02501 }
502 }
503
Vitaly Buka1c91e722020-01-26 05:56:22504 int size_increase_hint_;
Vitaly Buka0e9439f2017-03-16 00:51:57505 size_t enforce_changes_;
Vitaly Bukaaf8136f2017-06-09 23:40:12506 bool enforce_utf8_strings_;
Vitaly Bukaf62086c2020-01-29 09:11:23507 const ConstMessages& sources_;
Vitaly Bukae79e0182017-03-02 00:02:14508 Mutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09509};
510
Vitaly Buka5d013202017-02-25 00:50:11511namespace {
512
Vitaly Bukad4ab1e72017-03-04 07:51:19513struct MutateField : public FieldFunction<MutateField> {
Vitaly Buka5d013202017-02-25 00:50:11514 template <class T>
Vitaly Buka1c91e722020-01-26 05:56:22515 void ForType(const FieldInstance& field, int size_increase_hint,
Vitaly Bukaf62086c2020-01-29 09:11:23516 const ConstMessages& sources, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11517 T value;
518 field.Load(&value);
Vitaly Bukaf62086c2020-01-29 09:11:23519 FieldMutator(size_increase_hint, true, field.EnforceUtf8(), sources,
520 mutator)
Vitaly Bukaaf8136f2017-06-09 23:40:12521 .Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11522 field.Store(value);
523 }
Vitaly Buka5d013202017-02-25 00:50:11524};
525
Vitaly Bukad4ab1e72017-03-04 07:51:19526struct CreateField : public FieldFunction<CreateField> {
Vitaly Buka5d013202017-02-25 00:50:11527 public:
Vitaly Buka5d013202017-02-25 00:50:11528 template <class T>
Vitaly Buka1c91e722020-01-26 05:56:22529 void ForType(const FieldInstance& field, int size_increase_hint,
Vitaly Bukaf62086c2020-01-29 09:11:23530 const ConstMessages& sources, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11531 T value;
532 field.GetDefault(&value);
Vitaly Buka0e9439f2017-03-16 00:51:57533 FieldMutator field_mutator(size_increase_hint,
Vitaly Bukaaf8136f2017-06-09 23:40:12534 false /* defaults could be useful */,
Vitaly Bukaf62086c2020-01-29 09:11:23535 field.EnforceUtf8(), sources, mutator);
Vitaly Buka0e9439f2017-03-16 00:51:57536 field_mutator.Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11537 field.Create(value);
538 }
Vitaly Buka5d013202017-02-25 00:50:11539};
540
541} // namespace
542
Vitaly Buka379f5ab2019-08-31 23:11:59543void Mutator::Seed(uint32_t value) { random_.seed(value); }
Vitaly Buka432b5452016-12-09 22:42:09544
Vitaly Bukabaa13292020-01-26 03:39:28545void Mutator::Mutate(Message* message, size_t max_size_hint) {
Vitaly Bukaf62086c2020-01-29 09:11:23546 Messages messages;
547 messages.push_back(message);
548 ConstMessages sources(messages.begin(), messages.end());
549 MutateImpl(sources, messages, false,
Vitaly Buka1c91e722020-01-26 05:56:22550 static_cast<int>(max_size_hint) -
551 static_cast<int>(message->ByteSizeLong()));
Vitaly Buka0e17fd72016-11-18 18:02:46552
Vitaly Buka045acda2020-01-29 08:26:35553 PostProcessing(keep_initialized_, post_processors_, &random_)
554 .Run(message, kMaxInitializeDepth);
Vitaly Buka9eaf0632020-01-16 01:30:20555 assert(IsInitialized(*message));
Peter Foleyfe76ed62019-10-01 00:03:37556}
557
Vitaly Buka4b3d7832020-01-29 08:34:12558void Mutator::CrossOver(const Message& message1, Message* message2,
559 size_t max_size_hint) {
Vitaly Bukaf62086c2020-01-29 09:11:23560 Messages messages;
561 messages.push_back(message2);
562 ConstMessages sources;
563 sources.push_back(&message1);
Vitaly Buka1989ccb2020-02-04 23:40:30564 sources.push_back(message2);
Vitaly Buka4b3d7832020-01-29 08:34:12565 int size_increase_hint = static_cast<int>(max_size_hint) -
566 static_cast<int>(message2->ByteSizeLong());
Vitaly Bukaf62086c2020-01-29 09:11:23567 MutateImpl(sources, messages, true, size_increase_hint);
Vitaly Buka4b3d7832020-01-29 08:34:12568
569 PostProcessing(keep_initialized_, post_processors_, &random_)
570 .Run(message2, kMaxInitializeDepth);
571 assert(IsInitialized(*message2));
572}
573
Vitaly Bukad3600272020-01-27 07:24:10574void Mutator::RegisterPostProcessor(const Descriptor* desc,
Peter Foleyfe76ed62019-10-01 00:03:37575 PostProcess callback) {
576 post_processors_.emplace(desc, callback);
577}
578
Vitaly Bukaf62086c2020-01-29 09:11:23579bool Mutator::MutateImpl(const ConstMessages& sources, const Messages& messages,
Vitaly Buka9f357ae2020-01-27 07:17:11580 bool copy_clone_only, int size_increase_hint) {
Vitaly Buka1c91e722020-01-26 05:56:22581 if (size_increase_hint > 0) size_increase_hint /= 2;
Vitaly Bukac1839912020-01-27 06:32:57582 MutationBitset mutations;
Vitaly Buka9f357ae2020-01-27 07:17:11583 if (copy_clone_only) {
584 mutations[static_cast<size_t>(Mutation::Copy)] = true;
585 mutations[static_cast<size_t>(Mutation::Clone)] = true;
586 } else if (size_increase_hint <= 16) {
Vitaly Bukac1839912020-01-27 06:32:57587 mutations[static_cast<size_t>(Mutation::Delete)] = true;
588 } else {
589 mutations.set();
590 }
Vitaly Buka9f357ae2020-01-27 07:17:11591 while (mutations.any()) {
Vitaly Bukaf62086c2020-01-29 09:11:23592 MutationSampler mutation(keep_initialized_, mutations, &random_);
593 for (Message* message : messages) mutation.Sample(message);
594
Vitaly Buka3183b0d2019-09-06 22:11:10595 switch (mutation.mutation()) {
596 case Mutation::None:
Vitaly Buka9f357ae2020-01-27 07:17:11597 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10598 case Mutation::Add:
Vitaly Bukaf62086c2020-01-29 09:11:23599 CreateField()(mutation.field(), size_increase_hint, sources, this);
Vitaly Buka9f357ae2020-01-27 07:17:11600 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10601 case Mutation::Mutate:
Vitaly Bukaf62086c2020-01-29 09:11:23602 MutateField()(mutation.field(), size_increase_hint, sources, this);
Vitaly Buka9f357ae2020-01-27 07:17:11603 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10604 case Mutation::Delete:
605 DeleteField()(mutation.field());
Vitaly Buka9f357ae2020-01-27 07:17:11606 return true;
Vitaly Buka5635a7a2020-01-26 09:52:40607 case Mutation::Clone: {
Vitaly Buka9f357ae2020-01-27 07:17:11608 CreateDefaultField()(mutation.field());
Vitaly Buka5635a7a2020-01-26 09:52:40609 DataSourceSampler source_sampler(mutation.field(), &random_,
Vitaly Bukaf62086c2020-01-29 09:11:23610 size_increase_hint);
611 for (const Message* source : sources) source_sampler.Sample(*source);
Vitaly Buka1989ccb2020-02-04 23:40:30612 if (source_sampler.IsEmpty()) {
613 if (!IsProto3SimpleField(*mutation.field().descriptor()))
614 return true; // CreateField is enough for proto2.
615 break;
616 }
Vitaly Buka5635a7a2020-01-26 09:52:40617 CopyField()(source_sampler.field(), mutation.field());
Vitaly Buka9f357ae2020-01-27 07:17:11618 return true;
Vitaly Buka5635a7a2020-01-26 09:52:40619 }
Vitaly Buka3183b0d2019-09-06 22:11:10620 case Mutation::Copy: {
Vitaly Buka5cd166e2020-01-26 06:33:05621 DataSourceSampler source_sampler(mutation.field(), &random_,
Vitaly Bukaf62086c2020-01-29 09:11:23622 size_increase_hint);
623 for (const Message* source : sources) source_sampler.Sample(*source);
Vitaly Buka0f63f912020-01-24 23:02:45624 if (source_sampler.IsEmpty()) break;
625 CopyField()(source_sampler.field(), mutation.field());
Vitaly Buka9f357ae2020-01-27 07:17:11626 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10627 }
628 default:
629 assert(false && "unexpected mutation");
Vitaly Buka9f357ae2020-01-27 07:17:11630 return false;
Vitaly Buka3183b0d2019-09-06 22:11:10631 }
Vitaly Buka1989ccb2020-02-04 23:40:30632
633 // Don't try same mutation next time.
634 mutations[static_cast<size_t>(mutation.mutation())] = false;
Vitaly Buka3183b0d2019-09-06 22:11:10635 }
Vitaly Buka9f357ae2020-01-27 07:17:11636 return false;
Vitaly Buka3183b0d2019-09-06 22:11:10637}
638
Vitaly Buka379f5ab2019-08-31 23:11:59639int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14640
Vitaly Buka379f5ab2019-08-31 23:11:59641int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14642
643uint32_t Mutator::MutateUInt32(uint32_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59644 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32645}
646
Vitaly Bukae79e0182017-03-02 00:02:14647uint64_t Mutator::MutateUInt64(uint64_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59648 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32649}
650
Vitaly Buka379f5ab2019-08-31 23:11:59651float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32652
Vitaly Buka379f5ab2019-08-31 23:11:59653double Mutator::MutateDouble(double value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32654
Vitaly Bukae79e0182017-03-02 00:02:14655bool Mutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-04 02:57:32656
Vitaly Bukae79e0182017-03-02 00:02:14657size_t Mutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukaee1c76a2017-03-15 17:48:53658 if (item_count <= 1) return 0;
Vitaly Buka379f5ab2019-08-31 23:11:59659 return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-04 02:57:32660}
661
Vitaly Bukae79e0182017-03-02 00:02:14662std::string Mutator::MutateString(const std::string& value,
Vitaly Buka1c91e722020-01-26 05:56:22663 int size_increase_hint) {
Vitaly Buka4af611d2016-12-04 02:57:32664 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11665
Vitaly Buka379f5ab2019-08-31 23:11:59666 while (!result.empty() && GetRandomBool(&random_)) {
667 result.erase(GetRandomIndex(&random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09668 }
669
Vitaly Buka1c91e722020-01-26 05:56:22670 while (size_increase_hint > 0 &&
671 result.size() < static_cast<size_t>(size_increase_hint) &&
672 GetRandomBool(&random_)) {
Vitaly Buka379f5ab2019-08-31 23:11:59673 size_t index = GetRandomIndex(&random_, result.size() + 1);
674 result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09675 }
676
Vitaly Bukac020de12017-03-04 03:36:23677 if (result != value) return result;
678
679 if (result.empty()) {
Vitaly Buka379f5ab2019-08-31 23:11:59680 result.push_back(GetRandomIndex(&random_, 1 << 8));
Vitaly Bukac020de12017-03-04 03:36:23681 return result;
682 }
683
Vitaly Buka4af611d2016-12-04 02:57:32684 if (!result.empty())
Vitaly Buka379f5ab2019-08-31 23:11:59685 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
Vitaly Buka4af611d2016-12-04 02:57:32686 return result;
687}
Vitaly Buka432b5452016-12-09 22:42:09688
Vitaly Bukaaf8136f2017-06-09 23:40:12689std::string Mutator::MutateUtf8String(const std::string& value,
Vitaly Buka1c91e722020-01-26 05:56:22690 int size_increase_hint) {
Vitaly Bukaaf8136f2017-06-09 23:40:12691 std::string str = MutateString(value, size_increase_hint);
Vitaly Buka379f5ab2019-08-31 23:11:59692 FixUtf8String(&str, &random_);
Vitaly Bukaaf8136f2017-06-09 23:40:12693 return str;
694}
695
Vitaly Buka9eaf0632020-01-16 01:30:20696bool Mutator::IsInitialized(const Message& message) const {
697 if (!keep_initialized_ || message.IsInitialized()) return true;
698 std::cerr << "Uninitialized: " << message.DebugString() << "\n";
699 return false;
700}
701
Vitaly Buka432b5452016-12-09 22:42:09702} // namespace protobuf_mutator