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