blob: 415655beb09a803c2337a34b464bfab150fd1123 [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 Bukaf48c32b2020-04-10 19:17:2319#include <iostream>
Vitaly Buka0e17fd72016-11-18 18:02:4620#include <map>
Vitaly Bukadbc4c0f2020-01-29 09:22:2121#include <memory>
Vitaly Buka781853c2016-11-22 07:09:3522#include <random>
Vitaly Buka0e17fd72016-11-18 18:02:4623#include <string>
Vitaly Buka3521f472020-02-05 00:19:4124#include <utility>
Allen-Webbc4fa5912018-09-07 22:53:3025#include <vector>
Vitaly Buka00b61072016-10-19 23:22:5126
Vitaly Buka9dd2f8e2017-01-13 08:48:3127#include "src/field_instance.h"
Vitaly Bukaaf8136f2017-06-09 23:40:1228#include "src/utf8_fix.h"
Vitaly Buka9dd2f8e2017-01-13 08:48:3129#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 23:22:5130
Vitaly Bukaf86815c2017-02-27 22:19:1931namespace protobuf_mutator {
32
Vitaly Bukae635fea2020-02-04 19:59:1333using google::protobuf::Any;
Vitaly Buka6c6dbbe2017-02-22 21:58:2434using protobuf::Descriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2435using protobuf::FieldDescriptor;
Vitaly Buka796b1122017-03-03 22:42:0236using protobuf::FileDescriptor;
Vitaly Buka6c6dbbe2017-02-22 21:58:2437using protobuf::Message;
38using protobuf::OneofDescriptor;
39using protobuf::Reflection;
Vitaly Buka4782c142017-03-04 08:12:3240using protobuf::util::MessageDifferencer;
Vitaly Buka796b1122017-03-03 22:42:0241using std::placeholders::_1;
Vitaly Buka0e17fd72016-11-18 18:02:4642
43namespace {
44
Vitaly Bukae4eae602017-09-29 00:28:1245const int kMaxInitializeDepth = 200;
Vitaly Buka329fa462017-03-15 23:52:1746const uint64_t kDefaultMutateWeight = 1000000;
Vitaly Buka0e17fd72016-11-18 18:02:4647
Vitaly Bukac1839912020-01-27 06:32:5748enum class Mutation : uint8_t {
Vitaly Buka30de3092016-11-18 19:39:0749 None,
Vitaly Buka4af611d2016-12-04 02:57:3250 Add, // Adds new field with default value.
51 Mutate, // Mutates field contents.
52 Delete, // Deletes field.
Vitaly Bukaa3e59c72016-12-07 00:53:5653 Copy, // Copy values copied from another field.
Vitaly Buka5635a7a2020-01-26 09:52:4054 Clone, // Create new field with value copied from another.
Vitaly Bukac1839912020-01-27 06:32:5755
56 Last = Clone,
Vitaly Buka0e17fd72016-11-18 18:02:4657};
58
Vitaly Buka68e10c12020-03-26 20:41:3359using MutationBitset = std::bitset<static_cast<size_t>(Mutation::Last) + 1>;
Vitaly Bukac1839912020-01-27 06:32:5760
Vitaly Bukaf62086c2020-01-29 09:11:2361using Messages = std::vector<Message*>;
62using ConstMessages = std::vector<const Message*>;
63
Vitaly Bukab592ff02017-03-03 22:35:5264// Return random integer from [0, count)
Vitaly Bukaf62fe472017-03-02 07:05:1565size_t GetRandomIndex(RandomEngine* random, size_t count) {
Vitaly Bukab592ff02017-03-03 22:35:5266 assert(count > 0);
67 if (count == 1) return 0;
68 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
69}
70
Vitaly Buka4af611d2016-12-04 02:57:3271// Flips random bit in the buffer.
Vitaly Bukaf62fe472017-03-02 07:05:1572void FlipBit(size_t size, uint8_t* bytes, RandomEngine* random) {
Vitaly Bukab592ff02017-03-03 22:35:5273 size_t bit = GetRandomIndex(random, size * 8);
Vitaly Buka4af611d2016-12-04 02:57:3274 bytes[bit / 8] ^= (1u << (bit % 8));
75}
Vitaly Buka781853c2016-11-22 07:09:3576
Vitaly Buka4af611d2016-12-04 02:57:3277// Flips random bit in the value.
78template <class T>
Vitaly Bukaf62fe472017-03-02 07:05:1579T FlipBit(T value, RandomEngine* random) {
Vitaly Buka4af611d2016-12-04 02:57:3280 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
81 return value;
82}
Vitaly Buka781853c2016-11-22 07:09:3583
Vitaly Bukabeb90802017-02-28 23:28:1084// Return true with probability about 1-of-n.
Vitaly Bukaf62fe472017-03-02 07:05:1585bool GetRandomBool(RandomEngine* random, size_t n = 2) {
Vitaly Bukabeb90802017-02-28 23:28:1086 return GetRandomIndex(random, n) == 0;
87}
88
Vitaly Buka28ca0ee2017-03-05 05:35:4289bool IsProto3SimpleField(const FieldDescriptor& field) {
Sebastian Pippingdad575b2025-02-23 02:47:3890#if GOOGLE_PROTOBUF_VERSION >= 3012000 // commit bb30225f06c36399757dc698b409d5f79738e8d1 of >=3.12.0
91 const bool has_presence = field.has_presence();
92#else
93 // NOTE: This mimics Protobuf 3.21.12 ("3021012")
94 const bool has_presence = ! field.is_repeated() && (
95 field.cpp_type() == FieldDescriptor::CppType::CPPTYPE_MESSAGE
96 || field.containing_oneof()
97 || field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2
98 );
99#endif
100 return !field.is_repeated() && !has_presence;
Vitaly Buka28ca0ee2017-03-05 05:35:42101}
102
Vitaly Bukad4ab1e72017-03-04 07:51:19103struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
Vitaly Buka91ad7b02016-12-12 23:41:41104 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19105 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:41106 T value;
107 field.GetDefault(&value);
108 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:32109 }
Vitaly Buka91ad7b02016-12-12 23:41:41110};
Vitaly Bukabec52222016-12-09 22:29:32111
Vitaly Bukad4ab1e72017-03-04 07:51:19112struct DeleteField : public FieldFunction<DeleteField> {
Vitaly Buka91ad7b02016-12-12 23:41:41113 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19114 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 23:41:41115 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:32116 }
Vitaly Bukabec52222016-12-09 22:29:32117};
118
Vitaly Bukad4ab1e72017-03-04 07:51:19119struct CopyField : public FieldFunction<CopyField> {
Vitaly Bukaa3e59c72016-12-07 00:53:56120 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19121 void ForType(const ConstFieldInstance& source,
122 const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:56123 T value;
124 source.Load(&value);
125 field.Store(value);
126 }
Vitaly Bukaa3e59c72016-12-07 00:53:56127};
128
Vitaly Bukad4ab1e72017-03-04 07:51:19129struct AppendField : public FieldFunction<AppendField> {
Vitaly Bukaadfc27c2017-02-27 06:36:36130 template <class T>
Vitaly Bukad4ab1e72017-03-04 07:51:19131 void ForType(const ConstFieldInstance& source,
132 const FieldInstance& field) const {
Vitaly Bukaadfc27c2017-02-27 06:36:36133 T value;
134 source.Load(&value);
135 field.Create(value);
136 }
Vitaly Bukaadfc27c2017-02-27 06:36:36137};
138
Vitaly Buka2792ed72019-01-23 19:04:24139class CanCopyAndDifferentField
140 : public FieldFunction<CanCopyAndDifferentField, bool> {
Vitaly Buka4782c142017-03-04 08:12:32141 public:
142 template <class T>
Vitaly Buka5cd166e2020-01-26 06:33:05143 bool ForType(const ConstFieldInstance& src, const ConstFieldInstance& dst,
144 int size_increase_hint) const {
Vitaly Buka2792ed72019-01-23 19:04:24145 T s;
146 src.Load(&s);
147 if (!dst.CanStore(s)) return false;
148 T d;
149 dst.Load(&d);
Vitaly Buka5cd166e2020-01-26 06:33:05150 return SizeDiff(s, d) <= size_increase_hint && !IsEqual(s, d);
Vitaly Buka4782c142017-03-04 08:12:32151 }
152
153 private:
154 bool IsEqual(const ConstFieldInstance::Enum& a,
155 const ConstFieldInstance::Enum& b) const {
156 assert(a.count == b.count);
157 return a.index == b.index;
158 }
159
Vitaly Bukad3600272020-01-27 07:24:10160 bool IsEqual(const std::unique_ptr<Message>& a,
161 const std::unique_ptr<Message>& b) const {
Vitaly Buka4782c142017-03-04 08:12:32162 return MessageDifferencer::Equals(*a, *b);
163 }
164
165 template <class T>
166 bool IsEqual(const T& a, const T& b) const {
167 return a == b;
168 }
Vitaly Buka5cd166e2020-01-26 06:33:05169
Vitaly Bukad3600272020-01-27 07:24:10170 int64_t SizeDiff(const std::unique_ptr<Message>& src,
171 const std::unique_ptr<Message>& dst) const {
Vitaly Buka5cd166e2020-01-26 06:33:05172 return src->ByteSizeLong() - dst->ByteSizeLong();
173 }
174
175 int64_t SizeDiff(const std::string& src, const std::string& dst) const {
176 return src.size() - dst.size();
177 }
178
179 template <class T>
180 int64_t SizeDiff(const T&, const T&) const {
181 return 0;
182 }
Vitaly Buka4782c142017-03-04 08:12:32183};
184
Vitaly Buka4af611d2016-12-04 02:57:32185// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35186class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17187 public:
Vitaly Bukac1839912020-01-27 06:32:57188 MutationSampler(bool keep_initialized, MutationBitset allowed_mutations,
Vitaly Bukaf62086c2020-01-29 09:11:23189 RandomEngine* random)
Vitaly Buka4908d252020-01-25 03:10:34190 : keep_initialized_(keep_initialized),
Vitaly Bukac1839912020-01-27 06:32:57191 allowed_mutations_(allowed_mutations),
Vitaly Buka4908d252020-01-25 03:10:34192 random_(random),
Vitaly Bukaf62086c2020-01-29 09:11:23193 sampler_(random) {}
Vitaly Bukac9d22482016-11-21 21:29:17194
Vitaly Buka4af611d2016-12-04 02:57:32195 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32196 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32197
198 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09199 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32200
Vitaly Buka781853c2016-11-22 07:09:35201 void Sample(Message* message) {
Vitaly Bukaf62086c2020-01-29 09:11:23202 SampleImpl(message);
203 assert(mutation() != Mutation::None ||
204 !allowed_mutations_[static_cast<size_t>(Mutation::Mutate)] ||
205 message->GetDescriptor()->field_count() == 0);
206 }
207
208 private:
209 void SampleImpl(Message* message) {
Vitaly Buka781853c2016-11-22 07:09:35210 const Descriptor* descriptor = message->GetDescriptor();
211 const Reflection* reflection = message->GetReflection();
212
213 int field_count = descriptor->field_count();
214 for (int i = 0; i < field_count; ++i) {
215 const FieldDescriptor* field = descriptor->field(i);
216 if (const OneofDescriptor* oneof = field->containing_oneof()) {
217 // Handle entire oneof group on the first field.
218 if (field->index_in_oneof() == 0) {
Vitaly Buka2f660a52017-03-04 03:46:14219 assert(oneof->field_count());
220 const FieldDescriptor* current_field =
221 reflection->GetOneofFieldDescriptor(*message, oneof);
222 for (;;) {
223 const FieldDescriptor* add_field =
224 oneof->field(GetRandomIndex(random_, oneof->field_count()));
225 if (add_field != current_field) {
Vitaly Buka4908d252020-01-25 03:10:34226 Try({message, add_field}, Mutation::Add);
Vitaly Buka5635a7a2020-01-26 09:52:40227 Try({message, add_field}, Mutation::Clone);
Vitaly Buka2f660a52017-03-04 03:46:14228 break;
229 }
230 if (oneof->field_count() < 2) break;
231 }
232 if (current_field) {
Vitaly Buka4908d252020-01-25 03:10:34233 if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
234 Try({message, current_field}, Mutation::Mutate);
235 Try({message, current_field}, Mutation::Delete);
236 Try({message, current_field}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35237 }
238 }
239 } else {
240 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32241 int field_size = reflection->FieldSize(*message, field);
Vitaly Buka5635a7a2020-01-26 09:52:40242 size_t random_index = GetRandomIndex(random_, field_size + 1);
243 Try({message, field, random_index}, Mutation::Add);
244 Try({message, field, random_index}, Mutation::Clone);
Vitaly Buka781853c2016-11-22 07:09:35245
Vitaly Bukabec52222016-12-09 22:29:32246 if (field_size) {
247 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka4908d252020-01-25 03:10:34248 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
249 Try({message, field, random_index}, Mutation::Mutate);
250 Try({message, field, random_index}, Mutation::Delete);
251 Try({message, field, random_index}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35252 }
253 } else {
Vitaly Buka28ca0ee2017-03-05 05:35:42254 if (reflection->HasField(*message, field) ||
255 IsProto3SimpleField(*field)) {
Vitaly Buka4908d252020-01-25 03:10:34256 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
257 Try({message, field}, Mutation::Mutate);
Vitaly Buka28ca0ee2017-03-05 05:35:42258 if (!IsProto3SimpleField(*field) &&
259 (!field->is_required() || !keep_initialized_)) {
Vitaly Buka4908d252020-01-25 03:10:34260 Try({message, field}, Mutation::Delete);
Vitaly Buka28ca0ee2017-03-05 05:35:42261 }
Vitaly Buka4908d252020-01-25 03:10:34262 Try({message, field}, Mutation::Copy);
Vitaly Buka781853c2016-11-22 07:09:35263 } else {
Vitaly Buka4908d252020-01-25 03:10:34264 Try({message, field}, Mutation::Add);
Vitaly Buka5635a7a2020-01-26 09:52:40265 Try({message, field}, Mutation::Clone);
Vitaly Buka781853c2016-11-22 07:09:35266 }
267 }
268 }
269
270 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
271 if (field->is_repeated()) {
272 const int field_size = reflection->FieldSize(*message, field);
273 for (int j = 0; j < field_size; ++j)
Vitaly Bukaf62086c2020-01-29 09:11:23274 SampleImpl(reflection->MutableRepeatedMessage(message, field, j));
Vitaly Buka781853c2016-11-22 07:09:35275 } else if (reflection->HasField(*message, field)) {
Vitaly Bukaf62086c2020-01-29 09:11:23276 SampleImpl(reflection->MutableMessage(message, field));
Vitaly Buka781853c2016-11-22 07:09:35277 }
278 }
279 }
280 }
281
Vitaly Buka4908d252020-01-25 03:10:34282 void Try(const FieldInstance& field, Mutation mutation) {
283 assert(mutation != Mutation::None);
Vitaly Bukac1839912020-01-27 06:32:57284 if (!allowed_mutations_[static_cast<size_t>(mutation)]) return;
Vitaly Buka4908d252020-01-25 03:10:34285 sampler_.Try(kDefaultMutateWeight, {field, mutation});
286 }
287
Vitaly Buka781853c2016-11-22 07:09:35288 bool keep_initialized_ = false;
Vitaly Bukac1839912020-01-27 06:32:57289 MutationBitset allowed_mutations_;
Vitaly Buka4af611d2016-12-04 02:57:32290
Vitaly Bukaf62fe472017-03-02 07:05:15291 RandomEngine* random_;
Vitaly Buka4af611d2016-12-04 02:57:32292
293 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41294 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32295 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41296
Vitaly Bukabec52222016-12-09 22:29:32297 FieldInstance field;
298 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32299 };
Vitaly Bukaf62fe472017-03-02 07:05:15300 WeightedReservoirSampler<Result, RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17301};
302
Vitaly Bukaa3e59c72016-12-07 00:53:56303// Selects random field of compatible type to use for clone mutations.
304class DataSourceSampler {
305 public:
Vitaly Bukaf62fe472017-03-02 07:05:15306 DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
Vitaly Bukaf62086c2020-01-29 09:11:23307 int size_increase_hint)
Vitaly Buka5cd166e2020-01-26 06:33:05308 : match_(match),
309 random_(random),
310 size_increase_hint_(size_increase_hint),
Vitaly Bukaf62086c2020-01-29 09:11:23311 sampler_(random) {}
312
313 void Sample(const Message& message) { SampleImpl(message); }
Vitaly Bukaa3e59c72016-12-07 00:53:56314
315 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30316 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24317 assert(!IsEmpty());
318 return sampler_.selected();
319 }
320
321 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56322
323 private:
Vitaly Bukaf62086c2020-01-29 09:11:23324 void SampleImpl(const Message& message) {
Vitaly Buka0f63f912020-01-24 23:02:45325 const Descriptor* descriptor = message.GetDescriptor();
326 const Reflection* reflection = message.GetReflection();
Vitaly Bukaa3e59c72016-12-07 00:53:56327
328 int field_count = descriptor->field_count();
329 for (int i = 0; i < field_count; ++i) {
330 const FieldDescriptor* field = descriptor->field(i);
331 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
332 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45333 const int field_size = reflection->FieldSize(message, field);
Vitaly Bukaa3e59c72016-12-07 00:53:56334 for (int j = 0; j < field_size; ++j) {
Vitaly Bukaf62086c2020-01-29 09:11:23335 SampleImpl(reflection->GetRepeatedMessage(message, field, j));
Vitaly Bukaa3e59c72016-12-07 00:53:56336 }
Vitaly Buka0f63f912020-01-24 23:02:45337 } else if (reflection->HasField(message, field)) {
Vitaly Bukaf62086c2020-01-29 09:11:23338 SampleImpl(reflection->GetMessage(message, field));
Vitaly Bukaa3e59c72016-12-07 00:53:56339 }
340 }
341
342 if (field->cpp_type() != match_.cpp_type()) continue;
343 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
344 if (field->enum_type() != match_.enum_type()) continue;
345 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
346 if (field->message_type() != match_.message_type()) continue;
347 }
348
Vitaly Bukaa3e59c72016-12-07 00:53:56349 if (field->is_repeated()) {
Vitaly Buka0f63f912020-01-24 23:02:45350 if (int field_size = reflection->FieldSize(message, field)) {
351 ConstFieldInstance source(&message, field,
Vitaly Buka4782c142017-03-04 08:12:32352 GetRandomIndex(random_, field_size));
Vitaly Buka5cd166e2020-01-26 06:33:05353 if (CanCopyAndDifferentField()(source, match_, size_increase_hint_))
Vitaly Buka4782c142017-03-04 08:12:32354 sampler_.Try(field_size, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56355 }
356 } else {
Vitaly Buka0f63f912020-01-24 23:02:45357 if (reflection->HasField(message, field)) {
358 ConstFieldInstance source(&message, field);
Vitaly Buka5cd166e2020-01-26 06:33:05359 if (CanCopyAndDifferentField()(source, match_, size_increase_hint_))
Vitaly Buka2792ed72019-01-23 19:04:24360 sampler_.Try(1, source);
Vitaly Bukaa3e59c72016-12-07 00:53:56361 }
362 }
363 }
364 }
365
Vitaly Buka88712862017-02-27 06:21:30366 ConstFieldInstance match_;
Vitaly Bukaf62fe472017-03-02 07:05:15367 RandomEngine* random_;
Vitaly Buka5cd166e2020-01-26 06:33:05368 int size_increase_hint_;
Vitaly Bukaa3e59c72016-12-07 00:53:56369
Vitaly Bukaf62fe472017-03-02 07:05:15370 WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56371};
372
Vitaly Bukadbc4c0f2020-01-29 09:22:21373using UnpackedAny =
374 std::unordered_map<const Message*, std::unique_ptr<Message>>;
375
376const Descriptor* GetAnyTypeDescriptor(const Any& any) {
377 std::string type_name;
Vitaly Bukae635fea2020-02-04 19:59:13378 if (!Any::ParseAnyTypeUrl(std::string(any.type_url()), &type_name))
379 return nullptr;
Vitaly Bukadbc4c0f2020-01-29 09:22:21380 return any.descriptor()->file()->pool()->FindMessageTypeByName(type_name);
381}
382
383std::unique_ptr<Message> UnpackAny(const Any& any) {
384 const Descriptor* desc = GetAnyTypeDescriptor(any);
385 if (!desc) return {};
386 std::unique_ptr<Message> message(
387 any.GetReflection()->GetMessageFactory()->GetPrototype(desc)->New());
Vitaly Bukae635fea2020-02-04 19:59:13388 message->ParsePartialFromString(std::string(any.value()));
Vitaly Bukadbc4c0f2020-01-29 09:22:21389 return message;
390}
391
392const Any* CastToAny(const Message* message) {
Sebastian Pippingdad575b2025-02-23 02:47:38393#if GOOGLE_PROTOBUF_VERSION >= 3008000 // commit 1467e08d7c26a7087e5e5b14a4ab2755926e7249 of >=3.8.0
394 const Descriptor* any_descriptor = Any::GetDescriptor();
395#else
396 const Descriptor* any_descriptor = Any::descriptor();
397#endif
398 return any_descriptor == message->GetDescriptor()
Vitaly Buka4084aec2024-06-15 23:42:14399 ? protobuf::DownCastMessage<Any>(message)
Vitaly Bukadbc4c0f2020-01-29 09:22:21400 : nullptr;
401}
402
403Any* CastToAny(Message* message) {
Sebastian Pippingdad575b2025-02-23 02:47:38404#if GOOGLE_PROTOBUF_VERSION >= 3008000 // commit 1467e08d7c26a7087e5e5b14a4ab2755926e7249 of >=3.8.0
405 const Descriptor* any_descriptor = Any::GetDescriptor();
406#else
407 const Descriptor* any_descriptor = Any::descriptor();
408#endif
409 return any_descriptor == message->GetDescriptor()
Vitaly Buka4084aec2024-06-15 23:42:14410 ? protobuf::DownCastMessage<Any>(message)
Vitaly Bukadbc4c0f2020-01-29 09:22:21411 : nullptr;
412}
413
414std::unique_ptr<Message> UnpackIfAny(const Message& message) {
415 if (const Any* any = CastToAny(&message)) return UnpackAny(*any);
416 return {};
417}
418
419void UnpackAny(const Message& message, UnpackedAny* result) {
420 if (std::unique_ptr<Message> any = UnpackIfAny(message)) {
421 UnpackAny(*any, result);
422 result->emplace(&message, std::move(any));
423 return;
424 }
425
426 const Descriptor* descriptor = message.GetDescriptor();
427 const Reflection* reflection = message.GetReflection();
428
429 for (int i = 0; i < descriptor->field_count(); ++i) {
430 const FieldDescriptor* field = descriptor->field(i);
431 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
432 if (field->is_repeated()) {
433 const int field_size = reflection->FieldSize(message, field);
434 for (int j = 0; j < field_size; ++j) {
435 UnpackAny(reflection->GetRepeatedMessage(message, field, j), result);
436 }
437 } else if (reflection->HasField(message, field)) {
438 UnpackAny(reflection->GetMessage(message, field), result);
439 }
440 }
441 }
442}
443
Vitaly Buka045acda2020-01-29 08:26:35444class PostProcessing {
445 public:
Vitaly Bukaf62086c2020-01-29 09:11:23446 using PostProcessors =
447 std::unordered_multimap<const Descriptor*, Mutator::PostProcess>;
Vitaly Buka045acda2020-01-29 08:26:35448
449 PostProcessing(bool keep_initialized, const PostProcessors& post_processors,
Vitaly Buka3521f472020-02-05 00:19:41450 const UnpackedAny& any, RandomEngine* random)
Vitaly Buka045acda2020-01-29 08:26:35451 : keep_initialized_(keep_initialized),
452 post_processors_(post_processors),
Vitaly Bukadbc4c0f2020-01-29 09:22:21453 any_(any),
Vitaly Buka045acda2020-01-29 08:26:35454 random_(random) {}
455
456 void Run(Message* message, int max_depth) {
457 --max_depth;
458 const Descriptor* descriptor = message->GetDescriptor();
459
460 // Apply custom mutators in nested messages before packing any.
461 const Reflection* reflection = message->GetReflection();
462 for (int i = 0; i < descriptor->field_count(); i++) {
463 const FieldDescriptor* field = descriptor->field(i);
464 if (keep_initialized_ &&
465 (field->is_required() || descriptor->options().map_entry()) &&
466 !reflection->HasField(*message, field)) {
467 CreateDefaultField()(FieldInstance(message, field));
468 }
469
470 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
471
472 if (max_depth < 0 && !field->is_required()) {
473 // Clear deep optional fields to avoid stack overflow.
474 reflection->ClearField(message, field);
475 if (field->is_repeated())
476 assert(!reflection->FieldSize(*message, field));
477 else
478 assert(!reflection->HasField(*message, field));
479 continue;
480 }
481
482 if (field->is_repeated()) {
483 const int field_size = reflection->FieldSize(*message, field);
484 for (int j = 0; j < field_size; ++j) {
485 Message* nested_message =
486 reflection->MutableRepeatedMessage(message, field, j);
487 Run(nested_message, max_depth);
488 }
489 } else if (reflection->HasField(*message, field)) {
490 Message* nested_message = reflection->MutableMessage(message, field);
491 Run(nested_message, max_depth);
492 }
493 }
494
Vitaly Bukadbc4c0f2020-01-29 09:22:21495 if (Any* any = CastToAny(message)) {
496 if (max_depth < 0) {
497 // Clear deep Any fields to avoid stack overflow.
498 any->Clear();
499 } else {
500 auto It = any_.find(message);
501 if (It != any_.end()) {
502 Run(It->second.get(), max_depth);
Vitaly Bukae635fea2020-02-04 19:59:13503 std::string value;
504 It->second->SerializePartialToString(&value);
Sebastian Pipping57928f42025-02-23 02:48:36505 *any->mutable_value() = std::move(value);
Vitaly Bukadbc4c0f2020-01-29 09:22:21506 }
507 }
508 }
509
510 // Call user callback after message trimmed, initialized and packed.
Vitaly Buka045acda2020-01-29 08:26:35511 auto range = post_processors_.equal_range(descriptor);
512 for (auto it = range.first; it != range.second; ++it)
513 it->second(message, (*random_)());
514 }
515
516 private:
517 bool keep_initialized_;
518 const PostProcessors& post_processors_;
Vitaly Buka3521f472020-02-05 00:19:41519 const UnpackedAny& any_;
Vitaly Buka045acda2020-01-29 08:26:35520 RandomEngine* random_;
521};
522
Vitaly Buka0e17fd72016-11-18 18:02:46523} // namespace
524
Vitaly Buka5d013202017-02-25 00:50:11525class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09526 public:
Vitaly Buka1c91e722020-01-26 05:56:22527 FieldMutator(int size_increase_hint, bool enforce_changes,
Vitaly Bukaf62086c2020-01-29 09:11:23528 bool enforce_utf8_strings, const ConstMessages& sources,
Vitaly Buka0f63f912020-01-24 23:02:45529 Mutator* mutator)
Vitaly Buka0e9439f2017-03-16 00:51:57530 : size_increase_hint_(size_increase_hint),
531 enforce_changes_(enforce_changes),
Vitaly Bukaaf8136f2017-06-09 23:40:12532 enforce_utf8_strings_(enforce_utf8_strings),
Vitaly Bukaf62086c2020-01-29 09:11:23533 sources_(sources),
Vitaly Buka0e9439f2017-03-16 00:51:57534 mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41535
Vitaly Buka796b1122017-03-03 22:42:02536 void Mutate(int32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14537 RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02538 }
Vitaly Buka91ad7b02016-12-12 23:41:41539
Vitaly Buka796b1122017-03-03 22:42:02540 void Mutate(int64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14541 RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02542 }
Vitaly Buka91ad7b02016-12-12 23:41:41543
544 void Mutate(uint32_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14545 RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41546 }
547
548 void Mutate(uint64_t* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14549 RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 23:41:41550 }
551
Vitaly Buka796b1122017-03-03 22:42:02552 void Mutate(float* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14553 RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02554 }
Vitaly Buka91ad7b02016-12-12 23:41:41555
Vitaly Buka796b1122017-03-03 22:42:02556 void Mutate(double* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14557 RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02558 }
Vitaly Buka91ad7b02016-12-12 23:41:41559
Vitaly Buka796b1122017-03-03 22:42:02560 void Mutate(bool* value) const {
Vitaly Bukad7f943f2019-01-31 22:05:33561 RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1));
Vitaly Buka796b1122017-03-03 22:42:02562 }
Vitaly Buka91ad7b02016-12-12 23:41:41563
564 void Mutate(FieldInstance::Enum* value) const {
Vitaly Bukae79e0182017-03-02 00:02:14565 RepeatMutate(&value->index,
Vitaly Bukad7f943f2019-01-31 22:05:33566 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count));
Vitaly Buka91ad7b02016-12-12 23:41:41567 assert(value->index < value->count);
568 }
569
570 void Mutate(std::string* value) const {
Vitaly Bukaaf8136f2017-06-09 23:40:12571 if (enforce_utf8_strings_) {
572 RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1,
573 size_increase_hint_));
574 } else {
575 RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
576 size_increase_hint_));
577 }
Vitaly Buka91ad7b02016-12-12 23:41:41578 }
579
Vitaly Bukab2c4fb52017-03-16 18:50:40580 void Mutate(std::unique_ptr<Message>* message) const {
581 assert(!enforce_changes_);
582 assert(*message);
Vitaly Bukad7f943f2019-01-31 22:05:33583 if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_))
584 return;
Vitaly Bukaf62086c2020-01-29 09:11:23585 mutator_->MutateImpl(sources_, {message->get()}, false,
586 size_increase_hint_);
Vitaly Bukab2c4fb52017-03-16 18:50:40587 }
Vitaly Buka432b5452016-12-09 22:42:09588
Vitaly Buka5d013202017-02-25 00:50:11589 private:
Vitaly Buka796b1122017-03-03 22:42:02590 template <class T, class F>
Vitaly Bukad7f943f2019-01-31 22:05:33591 void RepeatMutate(T* value, F mutate) const {
Vitaly Buka0e9439f2017-03-16 00:51:57592 if (!enforce_changes_ &&
Vitaly Bukad7f943f2019-01-31 22:05:33593 GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) {
Vitaly Buka0e9439f2017-03-16 00:51:57594 return;
Vitaly Bukab2c4fb52017-03-16 18:50:40595 }
Vitaly Buka796b1122017-03-03 22:42:02596 T tmp = *value;
597 for (int i = 0; i < 10; ++i) {
598 *value = mutate(*value);
Vitaly Buka0e9439f2017-03-16 00:51:57599 if (!enforce_changes_ || *value != tmp) return;
Vitaly Buka796b1122017-03-03 22:42:02600 }
601 }
602
Vitaly Buka1c91e722020-01-26 05:56:22603 int size_increase_hint_;
Vitaly Buka0e9439f2017-03-16 00:51:57604 size_t enforce_changes_;
Vitaly Bukaaf8136f2017-06-09 23:40:12605 bool enforce_utf8_strings_;
Vitaly Bukaf62086c2020-01-29 09:11:23606 const ConstMessages& sources_;
Vitaly Bukae79e0182017-03-02 00:02:14607 Mutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09608};
609
Vitaly Buka5d013202017-02-25 00:50:11610namespace {
611
Vitaly Bukad4ab1e72017-03-04 07:51:19612struct MutateField : public FieldFunction<MutateField> {
Vitaly Buka5d013202017-02-25 00:50:11613 template <class T>
Vitaly Buka1c91e722020-01-26 05:56:22614 void ForType(const FieldInstance& field, int size_increase_hint,
Vitaly Bukaf62086c2020-01-29 09:11:23615 const ConstMessages& sources, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11616 T value;
617 field.Load(&value);
Vitaly Bukaf62086c2020-01-29 09:11:23618 FieldMutator(size_increase_hint, true, field.EnforceUtf8(), sources,
619 mutator)
Vitaly Bukaaf8136f2017-06-09 23:40:12620 .Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11621 field.Store(value);
622 }
Vitaly Buka5d013202017-02-25 00:50:11623};
624
Vitaly Bukad4ab1e72017-03-04 07:51:19625struct CreateField : public FieldFunction<CreateField> {
Vitaly Buka5d013202017-02-25 00:50:11626 public:
Vitaly Buka5d013202017-02-25 00:50:11627 template <class T>
Vitaly Buka1c91e722020-01-26 05:56:22628 void ForType(const FieldInstance& field, int size_increase_hint,
Vitaly Bukaf62086c2020-01-29 09:11:23629 const ConstMessages& sources, Mutator* mutator) const {
Vitaly Buka5d013202017-02-25 00:50:11630 T value;
631 field.GetDefault(&value);
Vitaly Buka0e9439f2017-03-16 00:51:57632 FieldMutator field_mutator(size_increase_hint,
Vitaly Bukaaf8136f2017-06-09 23:40:12633 false /* defaults could be useful */,
Vitaly Bukaf62086c2020-01-29 09:11:23634 field.EnforceUtf8(), sources, mutator);
Vitaly Buka0e9439f2017-03-16 00:51:57635 field_mutator.Mutate(&value);
Vitaly Buka5d013202017-02-25 00:50:11636 field.Create(value);
637 }
Vitaly Buka5d013202017-02-25 00:50:11638};
639
640} // namespace
641
Vitaly Buka379f5ab2019-08-31 23:11:59642void Mutator::Seed(uint32_t value) { random_.seed(value); }
Vitaly Buka432b5452016-12-09 22:42:09643
Vitaly Bukad82b5fb2020-07-29 06:41:42644void Mutator::Fix(Message* message) {
645 UnpackedAny any;
646 UnpackAny(*message, &any);
647
648 PostProcessing(keep_initialized_, post_processors_, any, &random_)
649 .Run(message, kMaxInitializeDepth);
650 assert(IsInitialized(*message));
651}
652
Vitaly Bukabaa13292020-01-26 03:39:28653void Mutator::Mutate(Message* message, size_t max_size_hint) {
Vitaly Bukadbc4c0f2020-01-29 09:22:21654 UnpackedAny any;
655 UnpackAny(*message, &any);
656
Vitaly Bukaf62086c2020-01-29 09:11:23657 Messages messages;
Vitaly Bukadbc4c0f2020-01-29 09:22:21658 messages.reserve(any.size() + 1);
Vitaly Bukaf62086c2020-01-29 09:11:23659 messages.push_back(message);
Vitaly Bukadbc4c0f2020-01-29 09:22:21660 for (const auto& kv : any) messages.push_back(kv.second.get());
661
Vitaly Bukaf62086c2020-01-29 09:11:23662 ConstMessages sources(messages.begin(), messages.end());
663 MutateImpl(sources, messages, false,
Vitaly Buka1c91e722020-01-26 05:56:22664 static_cast<int>(max_size_hint) -
665 static_cast<int>(message->ByteSizeLong()));
Vitaly Buka0e17fd72016-11-18 18:02:46666
Vitaly Bukadbc4c0f2020-01-29 09:22:21667 PostProcessing(keep_initialized_, post_processors_, any, &random_)
Vitaly Buka045acda2020-01-29 08:26:35668 .Run(message, kMaxInitializeDepth);
Vitaly Buka9eaf0632020-01-16 01:30:20669 assert(IsInitialized(*message));
Peter Foleyfe76ed62019-10-01 00:03:37670}
671
Vitaly Buka4b3d7832020-01-29 08:34:12672void Mutator::CrossOver(const Message& message1, Message* message2,
673 size_t max_size_hint) {
Vitaly Bukadbc4c0f2020-01-29 09:22:21674 UnpackedAny any;
675 UnpackAny(*message2, &any);
676
Vitaly Bukaf62086c2020-01-29 09:11:23677 Messages messages;
Vitaly Bukadbc4c0f2020-01-29 09:22:21678 messages.reserve(any.size() + 1);
Vitaly Bukaf62086c2020-01-29 09:11:23679 messages.push_back(message2);
Vitaly Bukadbc4c0f2020-01-29 09:22:21680 for (auto& kv : any) messages.push_back(kv.second.get());
681
682 UnpackAny(message1, &any);
683
Vitaly Bukaf62086c2020-01-29 09:11:23684 ConstMessages sources;
Vitaly Bukadbc4c0f2020-01-29 09:22:21685 sources.reserve(any.size() + 2);
Vitaly Bukaf62086c2020-01-29 09:11:23686 sources.push_back(&message1);
Vitaly Buka1989ccb2020-02-04 23:40:30687 sources.push_back(message2);
Vitaly Bukadbc4c0f2020-01-29 09:22:21688 for (const auto& kv : any) sources.push_back(kv.second.get());
Vitaly Buka4b3d7832020-01-29 08:34:12689
Vitaly Bukadbc4c0f2020-01-29 09:22:21690 MutateImpl(sources, messages, true,
691 static_cast<int>(max_size_hint) -
692 static_cast<int>(message2->ByteSizeLong()));
693
694 PostProcessing(keep_initialized_, post_processors_, any, &random_)
Vitaly Buka4b3d7832020-01-29 08:34:12695 .Run(message2, kMaxInitializeDepth);
696 assert(IsInitialized(*message2));
697}
698
Vitaly Bukad3600272020-01-27 07:24:10699void Mutator::RegisterPostProcessor(const Descriptor* desc,
Peter Foleyfe76ed62019-10-01 00:03:37700 PostProcess callback) {
701 post_processors_.emplace(desc, callback);
702}
703
Vitaly Bukaf62086c2020-01-29 09:11:23704bool Mutator::MutateImpl(const ConstMessages& sources, const Messages& messages,
Vitaly Buka9f357ae2020-01-27 07:17:11705 bool copy_clone_only, int size_increase_hint) {
Vitaly Bukac1839912020-01-27 06:32:57706 MutationBitset mutations;
Vitaly Buka9f357ae2020-01-27 07:17:11707 if (copy_clone_only) {
708 mutations[static_cast<size_t>(Mutation::Copy)] = true;
709 mutations[static_cast<size_t>(Mutation::Clone)] = true;
710 } else if (size_increase_hint <= 16) {
Vitaly Bukac1839912020-01-27 06:32:57711 mutations[static_cast<size_t>(Mutation::Delete)] = true;
712 } else {
713 mutations.set();
Vitaly Bukadfd73df2020-02-04 20:00:21714 mutations[static_cast<size_t>(Mutation::Copy)] = false;
715 mutations[static_cast<size_t>(Mutation::Clone)] = false;
Vitaly Bukac1839912020-01-27 06:32:57716 }
Vitaly Buka9f357ae2020-01-27 07:17:11717 while (mutations.any()) {
Vitaly Bukaf62086c2020-01-29 09:11:23718 MutationSampler mutation(keep_initialized_, mutations, &random_);
719 for (Message* message : messages) mutation.Sample(message);
720
Vitaly Buka3183b0d2019-09-06 22:11:10721 switch (mutation.mutation()) {
722 case Mutation::None:
Vitaly Buka9f357ae2020-01-27 07:17:11723 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10724 case Mutation::Add:
Vitaly Bukaf62086c2020-01-29 09:11:23725 CreateField()(mutation.field(), size_increase_hint, sources, this);
Vitaly Buka9f357ae2020-01-27 07:17:11726 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10727 case Mutation::Mutate:
Vitaly Bukaf62086c2020-01-29 09:11:23728 MutateField()(mutation.field(), size_increase_hint, sources, this);
Vitaly Buka9f357ae2020-01-27 07:17:11729 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10730 case Mutation::Delete:
731 DeleteField()(mutation.field());
Vitaly Buka9f357ae2020-01-27 07:17:11732 return true;
Vitaly Buka5635a7a2020-01-26 09:52:40733 case Mutation::Clone: {
Vitaly Buka9f357ae2020-01-27 07:17:11734 CreateDefaultField()(mutation.field());
Vitaly Buka5635a7a2020-01-26 09:52:40735 DataSourceSampler source_sampler(mutation.field(), &random_,
Vitaly Bukaf62086c2020-01-29 09:11:23736 size_increase_hint);
737 for (const Message* source : sources) source_sampler.Sample(*source);
Vitaly Buka1989ccb2020-02-04 23:40:30738 if (source_sampler.IsEmpty()) {
739 if (!IsProto3SimpleField(*mutation.field().descriptor()))
740 return true; // CreateField is enough for proto2.
741 break;
742 }
Vitaly Buka5635a7a2020-01-26 09:52:40743 CopyField()(source_sampler.field(), mutation.field());
Vitaly Buka9f357ae2020-01-27 07:17:11744 return true;
Vitaly Buka5635a7a2020-01-26 09:52:40745 }
Vitaly Buka3183b0d2019-09-06 22:11:10746 case Mutation::Copy: {
Vitaly Buka5cd166e2020-01-26 06:33:05747 DataSourceSampler source_sampler(mutation.field(), &random_,
Vitaly Bukaf62086c2020-01-29 09:11:23748 size_increase_hint);
749 for (const Message* source : sources) source_sampler.Sample(*source);
Vitaly Buka0f63f912020-01-24 23:02:45750 if (source_sampler.IsEmpty()) break;
751 CopyField()(source_sampler.field(), mutation.field());
Vitaly Buka9f357ae2020-01-27 07:17:11752 return true;
Vitaly Buka3183b0d2019-09-06 22:11:10753 }
754 default:
755 assert(false && "unexpected mutation");
Vitaly Buka9f357ae2020-01-27 07:17:11756 return false;
Vitaly Buka3183b0d2019-09-06 22:11:10757 }
Vitaly Buka1989ccb2020-02-04 23:40:30758
759 // Don't try same mutation next time.
760 mutations[static_cast<size_t>(mutation.mutation())] = false;
Vitaly Buka3183b0d2019-09-06 22:11:10761 }
Vitaly Buka9f357ae2020-01-27 07:17:11762 return false;
Vitaly Buka3183b0d2019-09-06 22:11:10763}
764
Vitaly Buka379f5ab2019-08-31 23:11:59765int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14766
Vitaly Buka379f5ab2019-08-31 23:11:59767int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, &random_); }
Vitaly Bukae79e0182017-03-02 00:02:14768
769uint32_t Mutator::MutateUInt32(uint32_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59770 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32771}
772
Vitaly Bukae79e0182017-03-02 00:02:14773uint64_t Mutator::MutateUInt64(uint64_t value) {
Vitaly Buka379f5ab2019-08-31 23:11:59774 return FlipBit(value, &random_);
Vitaly Buka4af611d2016-12-04 02:57:32775}
776
Vitaly Buka379f5ab2019-08-31 23:11:59777float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32778
Vitaly Buka379f5ab2019-08-31 23:11:59779double Mutator::MutateDouble(double value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-04 02:57:32780
Vitaly Bukae79e0182017-03-02 00:02:14781bool Mutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-04 02:57:32782
Vitaly Bukae79e0182017-03-02 00:02:14783size_t Mutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukaee1c76a2017-03-15 17:48:53784 if (item_count <= 1) return 0;
Vitaly Buka379f5ab2019-08-31 23:11:59785 return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-04 02:57:32786}
787
Vitaly Bukae79e0182017-03-02 00:02:14788std::string Mutator::MutateString(const std::string& value,
Vitaly Buka1c91e722020-01-26 05:56:22789 int size_increase_hint) {
Vitaly Buka4af611d2016-12-04 02:57:32790 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11791
Vitaly Buka379f5ab2019-08-31 23:11:59792 while (!result.empty() && GetRandomBool(&random_)) {
793 result.erase(GetRandomIndex(&random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09794 }
795
Vitaly Buka1c91e722020-01-26 05:56:22796 while (size_increase_hint > 0 &&
797 result.size() < static_cast<size_t>(size_increase_hint) &&
798 GetRandomBool(&random_)) {
Vitaly Buka379f5ab2019-08-31 23:11:59799 size_t index = GetRandomIndex(&random_, result.size() + 1);
800 result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09801 }
802
Vitaly Bukac020de12017-03-04 03:36:23803 if (result != value) return result;
804
805 if (result.empty()) {
Vitaly Buka379f5ab2019-08-31 23:11:59806 result.push_back(GetRandomIndex(&random_, 1 << 8));
Vitaly Bukac020de12017-03-04 03:36:23807 return result;
808 }
809
Vitaly Buka4af611d2016-12-04 02:57:32810 if (!result.empty())
Vitaly Buka379f5ab2019-08-31 23:11:59811 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
Vitaly Buka4af611d2016-12-04 02:57:32812 return result;
813}
Vitaly Buka432b5452016-12-09 22:42:09814
Vitaly Bukaaf8136f2017-06-09 23:40:12815std::string Mutator::MutateUtf8String(const std::string& value,
Vitaly Buka1c91e722020-01-26 05:56:22816 int size_increase_hint) {
Vitaly Bukaaf8136f2017-06-09 23:40:12817 std::string str = MutateString(value, size_increase_hint);
Vitaly Buka379f5ab2019-08-31 23:11:59818 FixUtf8String(&str, &random_);
Vitaly Bukaaf8136f2017-06-09 23:40:12819 return str;
820}
821
Vitaly Buka9eaf0632020-01-16 01:30:20822bool Mutator::IsInitialized(const Message& message) const {
823 if (!keep_initialized_ || message.IsInitialized()) return true;
Sebastian Pipping97a5f4f2025-02-05 20:45:40824 std::cerr << "Uninitialized: " << message.DebugString() << "\n";
Vitaly Buka9eaf0632020-01-16 01:30:20825 return false;
826}
827
Vitaly Buka432b5452016-12-09 22:42:09828} // namespace protobuf_mutator