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