/src/expat/build/libprotobuf-mutator/src/libprotobuf-mutator/src/mutator.cc
Line | Count | Source |
1 | | // 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 | | |
15 | | #include "src/mutator.h" |
16 | | |
17 | | #include <algorithm> |
18 | | #include <bitset> |
19 | | #include <iostream> |
20 | | #include <map> |
21 | | #include <memory> |
22 | | #include <random> |
23 | | #include <string> |
24 | | #include <utility> |
25 | | #include <vector> |
26 | | |
27 | | #include "src/field_instance.h" |
28 | | #include "src/utf8_fix.h" |
29 | | #include "src/weighted_reservoir_sampler.h" |
30 | | |
31 | | namespace protobuf_mutator { |
32 | | |
33 | | using google::protobuf::Any; |
34 | | using protobuf::Descriptor; |
35 | | using protobuf::FieldDescriptor; |
36 | | using protobuf::FileDescriptor; |
37 | | using protobuf::Message; |
38 | | using protobuf::OneofDescriptor; |
39 | | using protobuf::Reflection; |
40 | | using protobuf::util::MessageDifferencer; |
41 | | using std::placeholders::_1; |
42 | | |
43 | | namespace { |
44 | | |
45 | | const int kMaxInitializeDepth = 200; |
46 | | const uint64_t kDefaultMutateWeight = 1000000; |
47 | | |
48 | | enum class Mutation : uint8_t { |
49 | | None, |
50 | | Add, // Adds new field with default value. |
51 | | Mutate, // Mutates field contents. |
52 | | Delete, // Deletes field. |
53 | | Copy, // Copy values copied from another field. |
54 | | Clone, // Create new field with value copied from another. |
55 | | |
56 | | Last = Clone, |
57 | | }; |
58 | | |
59 | | using MutationBitset = std::bitset<static_cast<size_t>(Mutation::Last) + 1>; |
60 | | |
61 | | using Messages = std::vector<Message*>; |
62 | | using ConstMessages = std::vector<const Message*>; |
63 | | |
64 | | // Return random integer from [0, count) |
65 | 0 | size_t GetRandomIndex(RandomEngine* random, size_t count) { |
66 | 0 | assert(count > 0); |
67 | 0 | if (count == 1) return 0; |
68 | 0 | return std::uniform_int_distribution<size_t>(0, count - 1)(*random); |
69 | 0 | } |
70 | | |
71 | | // Flips random bit in the buffer. |
72 | 0 | void FlipBit(size_t size, uint8_t* bytes, RandomEngine* random) { |
73 | 0 | size_t bit = GetRandomIndex(random, size * 8); |
74 | 0 | bytes[bit / 8] ^= (1u << (bit % 8)); |
75 | 0 | } |
76 | | |
77 | | // Flips random bit in the value. |
78 | | template <class T> |
79 | 0 | T FlipBit(T value, RandomEngine* random) { |
80 | 0 | FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random); |
81 | 0 | return value; |
82 | 0 | } Unexecuted instantiation: mutator.cc:int protobuf_mutator::(anonymous namespace)::FlipBit<int>(int, std::linear_congruential_engine<unsigned long, 48271ul, 0ul, 2147483647ul>*) Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::FlipBit<long>(long, std::linear_congruential_engine<unsigned long, 48271ul, 0ul, 2147483647ul>*) Unexecuted instantiation: mutator.cc:unsigned int protobuf_mutator::(anonymous namespace)::FlipBit<unsigned int>(unsigned int, std::linear_congruential_engine<unsigned long, 48271ul, 0ul, 2147483647ul>*) Unexecuted instantiation: mutator.cc:unsigned long protobuf_mutator::(anonymous namespace)::FlipBit<unsigned long>(unsigned long, std::linear_congruential_engine<unsigned long, 48271ul, 0ul, 2147483647ul>*) Unexecuted instantiation: mutator.cc:float protobuf_mutator::(anonymous namespace)::FlipBit<float>(float, std::linear_congruential_engine<unsigned long, 48271ul, 0ul, 2147483647ul>*) Unexecuted instantiation: mutator.cc:double protobuf_mutator::(anonymous namespace)::FlipBit<double>(double, std::linear_congruential_engine<unsigned long, 48271ul, 0ul, 2147483647ul>*) |
83 | | |
84 | | // Return true with probability about 1-of-n. |
85 | 0 | bool GetRandomBool(RandomEngine* random, size_t n = 2) { |
86 | 0 | return GetRandomIndex(random, n) == 0; |
87 | 0 | } |
88 | | |
89 | 0 | bool IsProto3SimpleField(const FieldDescriptor& field) { |
90 | | #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 | 0 | const bool has_presence = ! field.is_repeated() && ( |
95 | 0 | field.cpp_type() == FieldDescriptor::CppType::CPPTYPE_MESSAGE |
96 | 0 | || field.containing_oneof() |
97 | 0 | || field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2 |
98 | 0 | ); |
99 | 0 | #endif |
100 | 0 | return !field.is_repeated() && !has_presence; |
101 | 0 | } |
102 | | |
103 | | struct CreateDefaultField : public FieldFunction<CreateDefaultField> { |
104 | | template <class T> |
105 | 4 | void ForType(const FieldInstance& field) const { |
106 | 4 | T value; |
107 | 4 | field.GetDefault(&value); |
108 | 4 | field.Create(value); |
109 | 4 | } Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<int>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<long>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<unsigned int>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<unsigned long>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<double>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<float>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<bool>(protobuf_mutator::FieldInstance const&) const mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<protobuf_mutator::ConstFieldInstance::Enum>(protobuf_mutator::FieldInstance const&) const Line | Count | Source | 105 | 4 | void ForType(const FieldInstance& field) const { | 106 | 4 | T value; | 107 | 4 | field.GetDefault(&value); | 108 | 4 | field.Create(value); | 109 | 4 | } |
Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateDefaultField::ForType<std::unique_ptr<google::protobuf::Message, std::default_delete<google::protobuf::Message> > >(protobuf_mutator::FieldInstance const&) const |
110 | | }; |
111 | | |
112 | | struct DeleteField : public FieldFunction<DeleteField> { |
113 | | template <class T> |
114 | 0 | void ForType(const FieldInstance& field) const { |
115 | 0 | field.Delete(); |
116 | 0 | } Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<int>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<long>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<unsigned int>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<unsigned long>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<double>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<float>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<bool>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<protobuf_mutator::ConstFieldInstance::Enum>(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::DeleteField::ForType<std::unique_ptr<google::protobuf::Message, std::default_delete<google::protobuf::Message> > >(protobuf_mutator::FieldInstance const&) const |
117 | | }; |
118 | | |
119 | | struct CopyField : public FieldFunction<CopyField> { |
120 | | template <class T> |
121 | | void ForType(const ConstFieldInstance& source, |
122 | 0 | const FieldInstance& field) const { |
123 | 0 | T value; |
124 | 0 | source.Load(&value); |
125 | 0 | field.Store(value); |
126 | 0 | } Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<int>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<long>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<unsigned int>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<unsigned long>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<double>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<float>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<bool>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<protobuf_mutator::ConstFieldInstance::Enum>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CopyField::ForType<std::unique_ptr<google::protobuf::Message, std::default_delete<google::protobuf::Message> > >(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::FieldInstance const&) const |
127 | | }; |
128 | | |
129 | | struct AppendField : public FieldFunction<AppendField> { |
130 | | template <class T> |
131 | | void ForType(const ConstFieldInstance& source, |
132 | | const FieldInstance& field) const { |
133 | | T value; |
134 | | source.Load(&value); |
135 | | field.Create(value); |
136 | | } |
137 | | }; |
138 | | |
139 | | class CanCopyAndDifferentField |
140 | | : public FieldFunction<CanCopyAndDifferentField, bool> { |
141 | | public: |
142 | | template <class T> |
143 | | bool ForType(const ConstFieldInstance& src, const ConstFieldInstance& dst, |
144 | 0 | int size_increase_hint) const { |
145 | 0 | T s; |
146 | 0 | src.Load(&s); |
147 | 0 | if (!dst.CanStore(s)) return false; |
148 | 0 | T d; |
149 | 0 | dst.Load(&d); |
150 | 0 | return SizeDiff(s, d) <= size_increase_hint && !IsEqual(s, d); |
151 | 0 | } Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<int>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<long>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<unsigned int>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<unsigned long>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<double>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<float>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<bool>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<protobuf_mutator::ConstFieldInstance::Enum>(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::ForType<std::unique_ptr<google::protobuf::Message, std::default_delete<google::protobuf::Message> > >(protobuf_mutator::ConstFieldInstance const&, protobuf_mutator::ConstFieldInstance const&, int) const |
152 | | |
153 | | private: |
154 | | bool IsEqual(const ConstFieldInstance::Enum& a, |
155 | 0 | const ConstFieldInstance::Enum& b) const { |
156 | 0 | assert(a.count == b.count); |
157 | 0 | return a.index == b.index; |
158 | 0 | } |
159 | | |
160 | | bool IsEqual(const std::unique_ptr<Message>& a, |
161 | 0 | const std::unique_ptr<Message>& b) const { |
162 | 0 | return MessageDifferencer::Equals(*a, *b); |
163 | 0 | } |
164 | | |
165 | | template <class T> |
166 | 0 | bool IsEqual(const T& a, const T& b) const { |
167 | 0 | return a == b; |
168 | 0 | } Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<int>(int const&, int const&) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<long>(long const&, long const&) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<unsigned int>(unsigned int const&, unsigned int const&) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<unsigned long>(unsigned long const&, unsigned long const&) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<double>(double const&, double const&) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<float>(float const&, float const&) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<bool>(bool const&, bool const&) const Unexecuted instantiation: mutator.cc:bool protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::IsEqual<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const |
169 | | |
170 | | int64_t SizeDiff(const std::unique_ptr<Message>& src, |
171 | 0 | const std::unique_ptr<Message>& dst) const { |
172 | 0 | return src->ByteSizeLong() - dst->ByteSizeLong(); |
173 | 0 | } |
174 | | |
175 | 0 | int64_t SizeDiff(const std::string& src, const std::string& dst) const { |
176 | 0 | return src.size() - dst.size(); |
177 | 0 | } |
178 | | |
179 | | template <class T> |
180 | 0 | int64_t SizeDiff(const T&, const T&) const { |
181 | 0 | return 0; |
182 | 0 | } Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<int>(int const&, int const&) const Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<long>(long const&, long const&) const Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<unsigned int>(unsigned int const&, unsigned int const&) const Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<unsigned long>(unsigned long const&, unsigned long const&) const Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<double>(double const&, double const&) const Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<float>(float const&, float const&) const Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<bool>(bool const&, bool const&) const Unexecuted instantiation: mutator.cc:long protobuf_mutator::(anonymous namespace)::CanCopyAndDifferentField::SizeDiff<protobuf_mutator::ConstFieldInstance::Enum>(protobuf_mutator::ConstFieldInstance::Enum const&, protobuf_mutator::ConstFieldInstance::Enum const&) const |
183 | | }; |
184 | | |
185 | | // Selects random field and mutation from the given proto message. |
186 | | class MutationSampler { |
187 | | public: |
188 | | MutationSampler(bool keep_initialized, MutationBitset allowed_mutations, |
189 | | RandomEngine* random) |
190 | 0 | : keep_initialized_(keep_initialized), |
191 | 0 | allowed_mutations_(allowed_mutations), |
192 | 0 | random_(random), |
193 | 0 | sampler_(random) {} |
194 | | |
195 | | // Returns selected field. |
196 | 0 | const FieldInstance& field() const { return sampler_.selected().field; } |
197 | | |
198 | | // Returns selected mutation. |
199 | 0 | Mutation mutation() const { return sampler_.selected().mutation; } |
200 | | |
201 | 0 | void Sample(Message* message) { |
202 | 0 | SampleImpl(message); |
203 | 0 | assert(mutation() != Mutation::None || |
204 | 0 | !allowed_mutations_[static_cast<size_t>(Mutation::Mutate)] || |
205 | 0 | message->GetDescriptor()->field_count() == 0); |
206 | 0 | } |
207 | | |
208 | | private: |
209 | 0 | void SampleImpl(Message* message) { |
210 | 0 | const Descriptor* descriptor = message->GetDescriptor(); |
211 | 0 | const Reflection* reflection = message->GetReflection(); |
212 | |
|
213 | 0 | int field_count = descriptor->field_count(); |
214 | 0 | for (int i = 0; i < field_count; ++i) { |
215 | 0 | const FieldDescriptor* field = descriptor->field(i); |
216 | 0 | if (const OneofDescriptor* oneof = field->containing_oneof()) { |
217 | | // Handle entire oneof group on the first field. |
218 | 0 | if (field->index_in_oneof() == 0) { |
219 | 0 | assert(oneof->field_count()); |
220 | 0 | const FieldDescriptor* current_field = |
221 | 0 | reflection->GetOneofFieldDescriptor(*message, oneof); |
222 | 0 | for (;;) { |
223 | 0 | const FieldDescriptor* add_field = |
224 | 0 | oneof->field(GetRandomIndex(random_, oneof->field_count())); |
225 | 0 | if (add_field != current_field) { |
226 | 0 | Try({message, add_field}, Mutation::Add); |
227 | 0 | Try({message, add_field}, Mutation::Clone); |
228 | 0 | break; |
229 | 0 | } |
230 | 0 | if (oneof->field_count() < 2) break; |
231 | 0 | } |
232 | 0 | if (current_field) { |
233 | 0 | if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) |
234 | 0 | Try({message, current_field}, Mutation::Mutate); |
235 | 0 | Try({message, current_field}, Mutation::Delete); |
236 | 0 | Try({message, current_field}, Mutation::Copy); |
237 | 0 | } |
238 | 0 | } |
239 | 0 | } else { |
240 | 0 | if (field->is_repeated()) { |
241 | 0 | int field_size = reflection->FieldSize(*message, field); |
242 | 0 | size_t random_index = GetRandomIndex(random_, field_size + 1); |
243 | 0 | Try({message, field, random_index}, Mutation::Add); |
244 | 0 | Try({message, field, random_index}, Mutation::Clone); |
245 | |
|
246 | 0 | if (field_size) { |
247 | 0 | size_t random_index = GetRandomIndex(random_, field_size); |
248 | 0 | if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) |
249 | 0 | Try({message, field, random_index}, Mutation::Mutate); |
250 | 0 | Try({message, field, random_index}, Mutation::Delete); |
251 | 0 | Try({message, field, random_index}, Mutation::Copy); |
252 | 0 | } |
253 | 0 | } else { |
254 | 0 | if (reflection->HasField(*message, field) || |
255 | 0 | IsProto3SimpleField(*field)) { |
256 | 0 | if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) |
257 | 0 | Try({message, field}, Mutation::Mutate); |
258 | 0 | if (!IsProto3SimpleField(*field) && |
259 | 0 | (!field->is_required() || !keep_initialized_)) { |
260 | 0 | Try({message, field}, Mutation::Delete); |
261 | 0 | } |
262 | 0 | Try({message, field}, Mutation::Copy); |
263 | 0 | } else { |
264 | 0 | Try({message, field}, Mutation::Add); |
265 | 0 | Try({message, field}, Mutation::Clone); |
266 | 0 | } |
267 | 0 | } |
268 | 0 | } |
269 | | |
270 | 0 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
271 | 0 | if (field->is_repeated()) { |
272 | 0 | const int field_size = reflection->FieldSize(*message, field); |
273 | 0 | for (int j = 0; j < field_size; ++j) |
274 | 0 | SampleImpl(reflection->MutableRepeatedMessage(message, field, j)); |
275 | 0 | } else if (reflection->HasField(*message, field)) { |
276 | 0 | SampleImpl(reflection->MutableMessage(message, field)); |
277 | 0 | } |
278 | 0 | } |
279 | 0 | } |
280 | 0 | } |
281 | | |
282 | 0 | void Try(const FieldInstance& field, Mutation mutation) { |
283 | 0 | assert(mutation != Mutation::None); |
284 | 0 | if (!allowed_mutations_[static_cast<size_t>(mutation)]) return; |
285 | 0 | sampler_.Try(kDefaultMutateWeight, {field, mutation}); |
286 | 0 | } |
287 | | |
288 | | bool keep_initialized_ = false; |
289 | | MutationBitset allowed_mutations_; |
290 | | |
291 | | RandomEngine* random_; |
292 | | |
293 | | struct Result { |
294 | 0 | Result() = default; |
295 | 0 | Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {} |
296 | | |
297 | | FieldInstance field; |
298 | | Mutation mutation = Mutation::None; |
299 | | }; |
300 | | WeightedReservoirSampler<Result, RandomEngine> sampler_; |
301 | | }; |
302 | | |
303 | | // Selects random field of compatible type to use for clone mutations. |
304 | | class DataSourceSampler { |
305 | | public: |
306 | | DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random, |
307 | | int size_increase_hint) |
308 | 0 | : match_(match), |
309 | 0 | random_(random), |
310 | 0 | size_increase_hint_(size_increase_hint), |
311 | 0 | sampler_(random) {} |
312 | | |
313 | 0 | void Sample(const Message& message) { SampleImpl(message); } |
314 | | |
315 | | // Returns selected field. |
316 | 0 | const ConstFieldInstance& field() const { |
317 | 0 | assert(!IsEmpty()); |
318 | 0 | return sampler_.selected(); |
319 | 0 | } |
320 | | |
321 | 0 | bool IsEmpty() const { return sampler_.IsEmpty(); } |
322 | | |
323 | | private: |
324 | 0 | void SampleImpl(const Message& message) { |
325 | 0 | const Descriptor* descriptor = message.GetDescriptor(); |
326 | 0 | const Reflection* reflection = message.GetReflection(); |
327 | |
|
328 | 0 | int field_count = descriptor->field_count(); |
329 | 0 | for (int i = 0; i < field_count; ++i) { |
330 | 0 | const FieldDescriptor* field = descriptor->field(i); |
331 | 0 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
332 | 0 | if (field->is_repeated()) { |
333 | 0 | const int field_size = reflection->FieldSize(message, field); |
334 | 0 | for (int j = 0; j < field_size; ++j) { |
335 | 0 | SampleImpl(reflection->GetRepeatedMessage(message, field, j)); |
336 | 0 | } |
337 | 0 | } else if (reflection->HasField(message, field)) { |
338 | 0 | SampleImpl(reflection->GetMessage(message, field)); |
339 | 0 | } |
340 | 0 | } |
341 | |
|
342 | 0 | if (field->cpp_type() != match_.cpp_type()) continue; |
343 | 0 | if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { |
344 | 0 | if (field->enum_type() != match_.enum_type()) continue; |
345 | 0 | } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
346 | 0 | if (field->message_type() != match_.message_type()) continue; |
347 | 0 | } |
348 | | |
349 | 0 | if (field->is_repeated()) { |
350 | 0 | if (int field_size = reflection->FieldSize(message, field)) { |
351 | 0 | ConstFieldInstance source(&message, field, |
352 | 0 | GetRandomIndex(random_, field_size)); |
353 | 0 | if (CanCopyAndDifferentField()(source, match_, size_increase_hint_)) |
354 | 0 | sampler_.Try(field_size, source); |
355 | 0 | } |
356 | 0 | } else { |
357 | 0 | if (reflection->HasField(message, field)) { |
358 | 0 | ConstFieldInstance source(&message, field); |
359 | 0 | if (CanCopyAndDifferentField()(source, match_, size_increase_hint_)) |
360 | 0 | sampler_.Try(1, source); |
361 | 0 | } |
362 | 0 | } |
363 | 0 | } |
364 | 0 | } |
365 | | |
366 | | ConstFieldInstance match_; |
367 | | RandomEngine* random_; |
368 | | int size_increase_hint_; |
369 | | |
370 | | WeightedReservoirSampler<ConstFieldInstance, RandomEngine> sampler_; |
371 | | }; |
372 | | |
373 | | using UnpackedAny = |
374 | | std::unordered_map<const Message*, std::unique_ptr<Message>>; |
375 | | |
376 | 0 | const Descriptor* GetAnyTypeDescriptor(const Any& any) { |
377 | 0 | std::string type_name; |
378 | 0 | if (!Any::ParseAnyTypeUrl(std::string(any.type_url()), &type_name)) |
379 | 0 | return nullptr; |
380 | 0 | return any.descriptor()->file()->pool()->FindMessageTypeByName(type_name); |
381 | 0 | } |
382 | | |
383 | 0 | std::unique_ptr<Message> UnpackAny(const Any& any) { |
384 | 0 | const Descriptor* desc = GetAnyTypeDescriptor(any); |
385 | 0 | if (!desc) return {}; |
386 | 0 | std::unique_ptr<Message> message( |
387 | 0 | any.GetReflection()->GetMessageFactory()->GetPrototype(desc)->New()); |
388 | 0 | message->ParsePartialFromString(std::string(any.value())); |
389 | 0 | return message; |
390 | 0 | } |
391 | | |
392 | 1.07M | const Any* CastToAny(const Message* message) { |
393 | | #if GOOGLE_PROTOBUF_VERSION >= 3008000 // commit 1467e08d7c26a7087e5e5b14a4ab2755926e7249 of >=3.8.0 |
394 | | const Descriptor* any_descriptor = Any::GetDescriptor(); |
395 | | #else |
396 | 1.07M | const Descriptor* any_descriptor = Any::descriptor(); |
397 | 1.07M | #endif |
398 | 1.07M | return any_descriptor == message->GetDescriptor() |
399 | 1.07M | ? protobuf::DownCastMessage<Any>(message) |
400 | 1.07M | : nullptr; |
401 | 1.07M | } |
402 | | |
403 | 1.07M | Any* CastToAny(Message* message) { |
404 | | #if GOOGLE_PROTOBUF_VERSION >= 3008000 // commit 1467e08d7c26a7087e5e5b14a4ab2755926e7249 of >=3.8.0 |
405 | | const Descriptor* any_descriptor = Any::GetDescriptor(); |
406 | | #else |
407 | 1.07M | const Descriptor* any_descriptor = Any::descriptor(); |
408 | 1.07M | #endif |
409 | 1.07M | return any_descriptor == message->GetDescriptor() |
410 | 1.07M | ? protobuf::DownCastMessage<Any>(message) |
411 | 1.07M | : nullptr; |
412 | 1.07M | } |
413 | | |
414 | 1.07M | std::unique_ptr<Message> UnpackIfAny(const Message& message) { |
415 | 1.07M | if (const Any* any = CastToAny(&message)) return UnpackAny(*any); |
416 | 1.07M | return {}; |
417 | 1.07M | } |
418 | | |
419 | 1.07M | void UnpackAny(const Message& message, UnpackedAny* result) { |
420 | 1.07M | if (std::unique_ptr<Message> any = UnpackIfAny(message)) { |
421 | 0 | UnpackAny(*any, result); |
422 | 0 | result->emplace(&message, std::move(any)); |
423 | 0 | return; |
424 | 0 | } |
425 | | |
426 | 1.07M | const Descriptor* descriptor = message.GetDescriptor(); |
427 | 1.07M | const Reflection* reflection = message.GetReflection(); |
428 | | |
429 | 5.32M | for (int i = 0; i < descriptor->field_count(); ++i) { |
430 | 4.25M | const FieldDescriptor* field = descriptor->field(i); |
431 | 4.25M | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
432 | 32.5k | if (field->is_repeated()) { |
433 | 32.5k | const int field_size = reflection->FieldSize(message, field); |
434 | 1.07M | for (int j = 0; j < field_size; ++j) { |
435 | 1.03M | UnpackAny(reflection->GetRepeatedMessage(message, field, j), result); |
436 | 1.03M | } |
437 | 32.5k | } else if (reflection->HasField(message, field)) { |
438 | 0 | UnpackAny(reflection->GetMessage(message, field), result); |
439 | 0 | } |
440 | 32.5k | } |
441 | 4.25M | } |
442 | 1.07M | } |
443 | | |
444 | | class PostProcessing { |
445 | | public: |
446 | | using PostProcessors = |
447 | | std::unordered_multimap<const Descriptor*, Mutator::PostProcess>; |
448 | | |
449 | | PostProcessing(bool keep_initialized, const PostProcessors& post_processors, |
450 | | const UnpackedAny& any, RandomEngine* random) |
451 | 32.5k | : keep_initialized_(keep_initialized), |
452 | 32.5k | post_processors_(post_processors), |
453 | 32.5k | any_(any), |
454 | 32.5k | random_(random) {} |
455 | | |
456 | 1.07M | void Run(Message* message, int max_depth) { |
457 | 1.07M | --max_depth; |
458 | 1.07M | const Descriptor* descriptor = message->GetDescriptor(); |
459 | | |
460 | | // Apply custom mutators in nested messages before packing any. |
461 | 1.07M | const Reflection* reflection = message->GetReflection(); |
462 | 5.32M | for (int i = 0; i < descriptor->field_count(); i++) { |
463 | 4.25M | const FieldDescriptor* field = descriptor->field(i); |
464 | 4.25M | if (keep_initialized_ && |
465 | 4.25M | (field->is_required() || descriptor->options().map_entry()) && |
466 | 32.5k | !reflection->HasField(*message, field)) { |
467 | 4 | CreateDefaultField()(FieldInstance(message, field)); |
468 | 4 | } |
469 | | |
470 | 4.25M | if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; |
471 | | |
472 | 32.5k | if (max_depth < 0 && !field->is_required()) { |
473 | | // Clear deep optional fields to avoid stack overflow. |
474 | 0 | reflection->ClearField(message, field); |
475 | 0 | if (field->is_repeated()) |
476 | 0 | assert(!reflection->FieldSize(*message, field)); |
477 | 0 | else |
478 | 0 | assert(!reflection->HasField(*message, field)); |
479 | 0 | continue; |
480 | 0 | } |
481 | | |
482 | 32.5k | if (field->is_repeated()) { |
483 | 32.5k | const int field_size = reflection->FieldSize(*message, field); |
484 | 1.07M | for (int j = 0; j < field_size; ++j) { |
485 | 1.03M | Message* nested_message = |
486 | 1.03M | reflection->MutableRepeatedMessage(message, field, j); |
487 | 1.03M | Run(nested_message, max_depth); |
488 | 1.03M | } |
489 | 32.5k | } else if (reflection->HasField(*message, field)) { |
490 | 0 | Message* nested_message = reflection->MutableMessage(message, field); |
491 | 0 | Run(nested_message, max_depth); |
492 | 0 | } |
493 | 32.5k | } |
494 | | |
495 | 1.07M | if (Any* any = CastToAny(message)) { |
496 | 0 | if (max_depth < 0) { |
497 | | // Clear deep Any fields to avoid stack overflow. |
498 | 0 | any->Clear(); |
499 | 0 | } else { |
500 | 0 | auto It = any_.find(message); |
501 | 0 | if (It != any_.end()) { |
502 | 0 | Run(It->second.get(), max_depth); |
503 | 0 | std::string value; |
504 | 0 | It->second->SerializePartialToString(&value); |
505 | 0 | *any->mutable_value() = std::move(value); |
506 | 0 | } |
507 | 0 | } |
508 | 0 | } |
509 | | |
510 | | // Call user callback after message trimmed, initialized and packed. |
511 | 1.07M | auto range = post_processors_.equal_range(descriptor); |
512 | 1.07M | for (auto it = range.first; it != range.second; ++it) |
513 | 0 | it->second(message, (*random_)()); |
514 | 1.07M | } |
515 | | |
516 | | private: |
517 | | bool keep_initialized_; |
518 | | const PostProcessors& post_processors_; |
519 | | const UnpackedAny& any_; |
520 | | RandomEngine* random_; |
521 | | }; |
522 | | |
523 | | } // namespace |
524 | | |
525 | | class FieldMutator { |
526 | | public: |
527 | | FieldMutator(int size_increase_hint, bool enforce_changes, |
528 | | bool enforce_utf8_strings, const ConstMessages& sources, |
529 | | Mutator* mutator) |
530 | 0 | : size_increase_hint_(size_increase_hint), |
531 | 0 | enforce_changes_(enforce_changes), |
532 | 0 | enforce_utf8_strings_(enforce_utf8_strings), |
533 | 0 | sources_(sources), |
534 | 0 | mutator_(mutator) {} |
535 | | |
536 | 0 | void Mutate(int32_t* value) const { |
537 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1)); |
538 | 0 | } |
539 | | |
540 | 0 | void Mutate(int64_t* value) const { |
541 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1)); |
542 | 0 | } |
543 | | |
544 | 0 | void Mutate(uint32_t* value) const { |
545 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1)); |
546 | 0 | } |
547 | | |
548 | 0 | void Mutate(uint64_t* value) const { |
549 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1)); |
550 | 0 | } |
551 | | |
552 | 0 | void Mutate(float* value) const { |
553 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1)); |
554 | 0 | } |
555 | | |
556 | 0 | void Mutate(double* value) const { |
557 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1)); |
558 | 0 | } |
559 | | |
560 | 0 | void Mutate(bool* value) const { |
561 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1)); |
562 | 0 | } |
563 | | |
564 | 0 | void Mutate(FieldInstance::Enum* value) const { |
565 | 0 | RepeatMutate(&value->index, |
566 | 0 | std::bind(&Mutator::MutateEnum, mutator_, _1, value->count)); |
567 | 0 | assert(value->index < value->count); |
568 | 0 | } |
569 | | |
570 | 0 | void Mutate(std::string* value) const { |
571 | 0 | if (enforce_utf8_strings_) { |
572 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateUtf8String, mutator_, _1, |
573 | 0 | size_increase_hint_)); |
574 | 0 | } else { |
575 | 0 | RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1, |
576 | 0 | size_increase_hint_)); |
577 | 0 | } |
578 | 0 | } |
579 | | |
580 | 0 | void Mutate(std::unique_ptr<Message>* message) const { |
581 | 0 | assert(!enforce_changes_); |
582 | 0 | assert(*message); |
583 | 0 | if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) |
584 | 0 | return; |
585 | 0 | mutator_->MutateImpl(sources_, {message->get()}, false, |
586 | 0 | size_increase_hint_); |
587 | 0 | } |
588 | | |
589 | | private: |
590 | | template <class T, class F> |
591 | 0 | void RepeatMutate(T* value, F mutate) const { |
592 | 0 | if (!enforce_changes_ && |
593 | 0 | GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_)) { |
594 | 0 | return; |
595 | 0 | } |
596 | 0 | T tmp = *value; |
597 | 0 | for (int i = 0; i < 10; ++i) { |
598 | 0 | *value = mutate(*value); |
599 | 0 | if (!enforce_changes_ || *value != tmp) return; |
600 | 0 | } |
601 | 0 | } Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<int, std::_Bind<int (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(int)> >(int*, std::_Bind<int (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(int)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<long, std::_Bind<long (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(long)> >(long*, std::_Bind<long (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(long)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<unsigned int, std::_Bind<unsigned int (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(unsigned int)> >(unsigned int*, std::_Bind<unsigned int (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(unsigned int)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<unsigned long, std::_Bind<unsigned long (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(unsigned long)> >(unsigned long*, std::_Bind<unsigned long (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(unsigned long)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<double, std::_Bind<double (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(double)> >(double*, std::_Bind<double (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(double)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<float, std::_Bind<float (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(float)> >(float*, std::_Bind<float (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(float)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<bool, std::_Bind<bool (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(bool)> >(bool*, std::_Bind<bool (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>))(bool)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<unsigned long, std::_Bind<unsigned long (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>, unsigned long))(unsigned long, unsigned long)> >(unsigned long*, std::_Bind<unsigned long (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>, unsigned long))(unsigned long, unsigned long)>) const Unexecuted instantiation: void protobuf_mutator::FieldMutator::RepeatMutate<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::_Bind<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>, int))(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)> >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::_Bind<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > (protobuf_mutator::Mutator::*(protobuf_mutator::Mutator*, std::_Placeholder<1>, int))(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)>) const |
602 | | |
603 | | int size_increase_hint_; |
604 | | size_t enforce_changes_; |
605 | | bool enforce_utf8_strings_; |
606 | | const ConstMessages& sources_; |
607 | | Mutator* mutator_; |
608 | | }; |
609 | | |
610 | | namespace { |
611 | | |
612 | | struct MutateField : public FieldFunction<MutateField> { |
613 | | template <class T> |
614 | | void ForType(const FieldInstance& field, int size_increase_hint, |
615 | 0 | const ConstMessages& sources, Mutator* mutator) const { |
616 | 0 | T value; |
617 | 0 | field.Load(&value); |
618 | 0 | FieldMutator(size_increase_hint, true, field.EnforceUtf8(), sources, |
619 | 0 | mutator) |
620 | 0 | .Mutate(&value); |
621 | 0 | field.Store(value); |
622 | 0 | } Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<int>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<long>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<unsigned int>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<unsigned long>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<double>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<float>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<bool>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<protobuf_mutator::ConstFieldInstance::Enum>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::MutateField::ForType<std::unique_ptr<google::protobuf::Message, std::default_delete<google::protobuf::Message> > >(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const |
623 | | }; |
624 | | |
625 | | struct CreateField : public FieldFunction<CreateField> { |
626 | | public: |
627 | | template <class T> |
628 | | void ForType(const FieldInstance& field, int size_increase_hint, |
629 | 0 | const ConstMessages& sources, Mutator* mutator) const { |
630 | 0 | T value; |
631 | 0 | field.GetDefault(&value); |
632 | 0 | FieldMutator field_mutator(size_increase_hint, |
633 | 0 | false /* defaults could be useful */, |
634 | 0 | field.EnforceUtf8(), sources, mutator); |
635 | 0 | field_mutator.Mutate(&value); |
636 | 0 | field.Create(value); |
637 | 0 | } Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<int>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<long>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<unsigned int>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<unsigned long>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<double>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<float>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<bool>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<protobuf_mutator::ConstFieldInstance::Enum>(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const Unexecuted instantiation: mutator.cc:void protobuf_mutator::(anonymous namespace)::CreateField::ForType<std::unique_ptr<google::protobuf::Message, std::default_delete<google::protobuf::Message> > >(protobuf_mutator::FieldInstance const&, int, std::vector<google::protobuf::Message const*, std::allocator<google::protobuf::Message const*> > const&, protobuf_mutator::Mutator*) const |
638 | | }; |
639 | | |
640 | | } // namespace |
641 | | |
642 | 32.5k | void Mutator::Seed(uint32_t value) { random_.seed(value); } |
643 | | |
644 | 32.5k | void Mutator::Fix(Message* message) { |
645 | 32.5k | UnpackedAny any; |
646 | 32.5k | UnpackAny(*message, &any); |
647 | | |
648 | 32.5k | PostProcessing(keep_initialized_, post_processors_, any, &random_) |
649 | 32.5k | .Run(message, kMaxInitializeDepth); |
650 | 32.5k | assert(IsInitialized(*message)); |
651 | 32.5k | } |
652 | | |
653 | 0 | void Mutator::Mutate(Message* message, size_t max_size_hint) { |
654 | 0 | UnpackedAny any; |
655 | 0 | UnpackAny(*message, &any); |
656 | |
|
657 | 0 | Messages messages; |
658 | 0 | messages.reserve(any.size() + 1); |
659 | 0 | messages.push_back(message); |
660 | 0 | for (const auto& kv : any) messages.push_back(kv.second.get()); |
661 | |
|
662 | 0 | ConstMessages sources(messages.begin(), messages.end()); |
663 | 0 | MutateImpl(sources, messages, false, |
664 | 0 | static_cast<int>(max_size_hint) - |
665 | 0 | static_cast<int>(message->ByteSizeLong())); |
666 | |
|
667 | 0 | PostProcessing(keep_initialized_, post_processors_, any, &random_) |
668 | 0 | .Run(message, kMaxInitializeDepth); |
669 | 0 | assert(IsInitialized(*message)); |
670 | 0 | } |
671 | | |
672 | | void Mutator::CrossOver(const Message& message1, Message* message2, |
673 | 0 | size_t max_size_hint) { |
674 | 0 | UnpackedAny any; |
675 | 0 | UnpackAny(*message2, &any); |
676 | |
|
677 | 0 | Messages messages; |
678 | 0 | messages.reserve(any.size() + 1); |
679 | 0 | messages.push_back(message2); |
680 | 0 | for (auto& kv : any) messages.push_back(kv.second.get()); |
681 | |
|
682 | 0 | UnpackAny(message1, &any); |
683 | |
|
684 | 0 | ConstMessages sources; |
685 | 0 | sources.reserve(any.size() + 2); |
686 | 0 | sources.push_back(&message1); |
687 | 0 | sources.push_back(message2); |
688 | 0 | for (const auto& kv : any) sources.push_back(kv.second.get()); |
689 | |
|
690 | 0 | MutateImpl(sources, messages, true, |
691 | 0 | static_cast<int>(max_size_hint) - |
692 | 0 | static_cast<int>(message2->ByteSizeLong())); |
693 | |
|
694 | 0 | PostProcessing(keep_initialized_, post_processors_, any, &random_) |
695 | 0 | .Run(message2, kMaxInitializeDepth); |
696 | 0 | assert(IsInitialized(*message2)); |
697 | 0 | } |
698 | | |
699 | | void Mutator::RegisterPostProcessor(const Descriptor* desc, |
700 | 0 | PostProcess callback) { |
701 | 0 | post_processors_.emplace(desc, callback); |
702 | 0 | } |
703 | | |
704 | | bool Mutator::MutateImpl(const ConstMessages& sources, const Messages& messages, |
705 | 0 | bool copy_clone_only, int size_increase_hint) { |
706 | 0 | MutationBitset mutations; |
707 | 0 | if (copy_clone_only) { |
708 | 0 | mutations[static_cast<size_t>(Mutation::Copy)] = true; |
709 | 0 | mutations[static_cast<size_t>(Mutation::Clone)] = true; |
710 | 0 | } else if (size_increase_hint <= 16) { |
711 | 0 | mutations[static_cast<size_t>(Mutation::Delete)] = true; |
712 | 0 | } else { |
713 | 0 | mutations.set(); |
714 | 0 | mutations[static_cast<size_t>(Mutation::Copy)] = false; |
715 | 0 | mutations[static_cast<size_t>(Mutation::Clone)] = false; |
716 | 0 | } |
717 | 0 | while (mutations.any()) { |
718 | 0 | MutationSampler mutation(keep_initialized_, mutations, &random_); |
719 | 0 | for (Message* message : messages) mutation.Sample(message); |
720 | |
|
721 | 0 | switch (mutation.mutation()) { |
722 | 0 | case Mutation::None: |
723 | 0 | return true; |
724 | 0 | case Mutation::Add: |
725 | 0 | CreateField()(mutation.field(), size_increase_hint, sources, this); |
726 | 0 | return true; |
727 | 0 | case Mutation::Mutate: |
728 | 0 | MutateField()(mutation.field(), size_increase_hint, sources, this); |
729 | 0 | return true; |
730 | 0 | case Mutation::Delete: |
731 | 0 | DeleteField()(mutation.field()); |
732 | 0 | return true; |
733 | 0 | case Mutation::Clone: { |
734 | 0 | CreateDefaultField()(mutation.field()); |
735 | 0 | DataSourceSampler source_sampler(mutation.field(), &random_, |
736 | 0 | size_increase_hint); |
737 | 0 | for (const Message* source : sources) source_sampler.Sample(*source); |
738 | 0 | if (source_sampler.IsEmpty()) { |
739 | 0 | if (!IsProto3SimpleField(*mutation.field().descriptor())) |
740 | 0 | return true; // CreateField is enough for proto2. |
741 | 0 | break; |
742 | 0 | } |
743 | 0 | CopyField()(source_sampler.field(), mutation.field()); |
744 | 0 | return true; |
745 | 0 | } |
746 | 0 | case Mutation::Copy: { |
747 | 0 | DataSourceSampler source_sampler(mutation.field(), &random_, |
748 | 0 | size_increase_hint); |
749 | 0 | for (const Message* source : sources) source_sampler.Sample(*source); |
750 | 0 | if (source_sampler.IsEmpty()) break; |
751 | 0 | CopyField()(source_sampler.field(), mutation.field()); |
752 | 0 | return true; |
753 | 0 | } |
754 | 0 | default: |
755 | 0 | assert(false && "unexpected mutation"); |
756 | 0 | return false; |
757 | 0 | } |
758 | | |
759 | | // Don't try same mutation next time. |
760 | 0 | mutations[static_cast<size_t>(mutation.mutation())] = false; |
761 | 0 | } |
762 | 0 | return false; |
763 | 0 | } |
764 | | |
765 | 0 | int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); } |
766 | | |
767 | 0 | int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, &random_); } |
768 | | |
769 | 0 | uint32_t Mutator::MutateUInt32(uint32_t value) { |
770 | 0 | return FlipBit(value, &random_); |
771 | 0 | } |
772 | | |
773 | 0 | uint64_t Mutator::MutateUInt64(uint64_t value) { |
774 | 0 | return FlipBit(value, &random_); |
775 | 0 | } |
776 | | |
777 | 0 | float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); } |
778 | | |
779 | 0 | double Mutator::MutateDouble(double value) { return FlipBit(value, &random_); } |
780 | | |
781 | 0 | bool Mutator::MutateBool(bool value) { return !value; } |
782 | | |
783 | 0 | size_t Mutator::MutateEnum(size_t index, size_t item_count) { |
784 | 0 | if (item_count <= 1) return 0; |
785 | 0 | return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count; |
786 | 0 | } |
787 | | |
788 | | std::string Mutator::MutateString(const std::string& value, |
789 | 0 | int size_increase_hint) { |
790 | 0 | std::string result = value; |
791 | |
|
792 | 0 | while (!result.empty() && GetRandomBool(&random_)) { |
793 | 0 | result.erase(GetRandomIndex(&random_, result.size()), 1); |
794 | 0 | } |
795 | |
|
796 | 0 | while (size_increase_hint > 0 && |
797 | 0 | result.size() < static_cast<size_t>(size_increase_hint) && |
798 | 0 | GetRandomBool(&random_)) { |
799 | 0 | size_t index = GetRandomIndex(&random_, result.size() + 1); |
800 | 0 | result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8)); |
801 | 0 | } |
802 | |
|
803 | 0 | if (result != value) return result; |
804 | | |
805 | 0 | if (result.empty()) { |
806 | 0 | result.push_back(GetRandomIndex(&random_, 1 << 8)); |
807 | 0 | return result; |
808 | 0 | } |
809 | | |
810 | 0 | if (!result.empty()) |
811 | 0 | FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_); |
812 | 0 | return result; |
813 | 0 | } |
814 | | |
815 | | std::string Mutator::MutateUtf8String(const std::string& value, |
816 | 0 | int size_increase_hint) { |
817 | 0 | std::string str = MutateString(value, size_increase_hint); |
818 | 0 | FixUtf8String(&str, &random_); |
819 | 0 | return str; |
820 | 0 | } |
821 | | |
822 | 32.5k | bool Mutator::IsInitialized(const Message& message) const { |
823 | 32.5k | if (!keep_initialized_ || message.IsInitialized()) return true; |
824 | 0 | std::cerr << "Uninitialized: " << message.DebugString() << "\n"; |
825 | 0 | return false; |
826 | 32.5k | } |
827 | | |
828 | | } // namespace protobuf_mutator |