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 #ifndef SRC_MUTATOR_H_ 16 #define SRC_MUTATOR_H_ 17 18 #include <stddef.h> 19 #include <stdint.h> 20 21 #include <functional> 22 #include <memory> 23 #include <random> 24 #include <string> 25 #include <unordered_map> 26 #include <vector> 27 28 #include "port/protobuf.h" 29 #include "src/random.h" 30 31 namespace protobuf_mutator { 32 33 // Randomly makes incremental change in the given protobuf. 34 // Usage example: 35 // protobuf_mutator::Mutator mutator(1); 36 // MyMessage message; 37 // message.ParseFromString(encoded_message); 38 // mutator.Mutate(&message, 10000); 39 // 40 // Class implements very basic mutations of fields. E.g. it just flips bits for 41 // integers, floats and strings. Also it increases, decreases size of 42 // strings only by one. For better results users should override 43 // protobuf_mutator::Mutator::Mutate* methods with more useful logic, e.g. using 44 // library like libFuzzer. 45 class Mutator { 46 public: 47 // seed: value to initialize random number generator. 48 Mutator() = default; 49 virtual ~Mutator() = default; 50 51 // Initialized internal random number generator. 52 void Seed(uint32_t value); 53 54 // message: message to mutate. 55 // max_size_hint: approximate max ByteSize() of resulting message. Method does 56 // not guarantee that real result will be strictly smaller than value. Caller 57 // could repeat mutation if result was larger than expected. 58 void Mutate(protobuf::Message* message, size_t max_size_hint); 59 60 void CrossOver(const protobuf::Message& message1, protobuf::Message* message2, 61 size_t max_size_hint); 62 63 // Callback to postprocess mutations. 64 // Implementation should use seed to initialize random number generators. 65 using PostProcess = 66 std::function<void(protobuf::Message* message, unsigned int seed)>; 67 68 // Register callback which will be called after every message mutation. 69 // In this callback fuzzer may adjust content of the message or mutate some 70 // fields in some fuzzer specific way. 71 void RegisterPostProcessor(const protobuf::Descriptor* desc, 72 PostProcess callback); 73 74 protected: 75 // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size). 76 virtual int32_t MutateInt32(int32_t value); 77 virtual int64_t MutateInt64(int64_t value); 78 virtual uint32_t MutateUInt32(uint32_t value); 79 virtual uint64_t MutateUInt64(uint64_t value); 80 virtual float MutateFloat(float value); 81 virtual double MutateDouble(double value); 82 virtual bool MutateBool(bool value); 83 virtual size_t MutateEnum(size_t index, size_t item_count); 84 virtual std::string MutateString(const std::string& value, 85 int size_increase_hint); 86 random()87 RandomEngine* random() { return &random_; } 88 89 private: 90 friend class FieldMutator; 91 friend class TestMutator; 92 bool MutateImpl(const std::vector<const protobuf::Message*>& sources, 93 const std::vector<protobuf::Message*>& messages, 94 bool copy_clone_only, int size_increase_hint); 95 std::string MutateUtf8String(const std::string& value, 96 int size_increase_hint); 97 bool IsInitialized(const protobuf::Message& message) const; 98 bool keep_initialized_ = true; 99 size_t random_to_default_ratio_ = 100; 100 RandomEngine random_; 101 using PostProcessors = 102 std::unordered_multimap<const protobuf::Descriptor*, PostProcess>; 103 PostProcessors post_processors_; 104 }; 105 106 } // namespace protobuf_mutator 107 108 #endif // SRC_MUTATOR_H_ 109