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 // Makes message initialized and calls post processors to make it valid. 64 void Fix(protobuf::Message* message); 65 66 // Callback to postprocess mutations. 67 // Implementation should use seed to initialize random number generators. 68 using PostProcess = 69 std::function<void(protobuf::Message* message, unsigned int seed)>; 70 71 // Register callback which will be called after every message mutation. 72 // In this callback fuzzer may adjust content of the message or mutate some 73 // fields in some fuzzer specific way. 74 void RegisterPostProcessor(const protobuf::Descriptor* desc, 75 PostProcess callback); 76 77 protected: 78 // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size). 79 virtual int32_t MutateInt32(int32_t value); 80 virtual int64_t MutateInt64(int64_t value); 81 virtual uint32_t MutateUInt32(uint32_t value); 82 virtual uint64_t MutateUInt64(uint64_t value); 83 virtual float MutateFloat(float value); 84 virtual double MutateDouble(double value); 85 virtual bool MutateBool(bool value); 86 virtual size_t MutateEnum(size_t index, size_t item_count); 87 virtual std::string MutateString(const std::string& value, 88 int size_increase_hint); 89 random()90 RandomEngine* random() { return &random_; } 91 92 private: 93 friend class FieldMutator; 94 friend class TestMutator; 95 bool MutateImpl(const std::vector<const protobuf::Message*>& sources, 96 const std::vector<protobuf::Message*>& messages, 97 bool copy_clone_only, int size_increase_hint); 98 std::string MutateUtf8String(const std::string& value, 99 int size_increase_hint); 100 bool IsInitialized(const protobuf::Message& message) const; 101 bool keep_initialized_ = true; 102 size_t random_to_default_ratio_ = 100; 103 RandomEngine random_; 104 using PostProcessors = 105 std::unordered_multimap<const protobuf::Descriptor*, PostProcess>; 106 PostProcessors post_processors_; 107 }; 108 109 } // namespace protobuf_mutator 110 111 #endif // SRC_MUTATOR_H_ 112