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 <memory> 22 #include <random> 23 #include <string> 24 25 #include "port/protobuf.h" 26 #include "src/random.h" 27 28 namespace protobuf_mutator { 29 30 // Randomly makes incremental change in the given protobuf. 31 // Usage example: 32 // protobuf_mutator::Mutator mutator(1); 33 // MyMessage message; 34 // message.ParseFromString(encoded_message); 35 // mutator.Mutate(&message, 10000); 36 // 37 // Class implements very basic mutations of fields. E.g. it just flips bits for 38 // integers, floats and strings. Also it increases, decreases size of 39 // strings only by one. For better results users should override 40 // protobuf_mutator::Mutator::Mutate* methods with more useful logic, e.g. using 41 // library like libFuzzer. 42 class Mutator { 43 public: 44 // seed: value to initialize random number generator. 45 explicit Mutator(RandomEngine* random); 46 virtual ~Mutator() = default; 47 48 // message: message to mutate. 49 // size_increase_hint: approximate number of bytes which can be added to the 50 // message. Method does not guarantee that real result size increase will be 51 // less than the value. It only changes probabilities of mutations which can 52 // cause size increase. Caller could repeat mutation if result was larger than 53 // requested. 54 void Mutate(protobuf::Message* message, size_t size_increase_hint); 55 56 void CrossOver(const protobuf::Message& message1, 57 protobuf::Message* message2); 58 59 protected: 60 // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size). 61 virtual int32_t MutateInt32(int32_t value); 62 virtual int64_t MutateInt64(int64_t value); 63 virtual uint32_t MutateUInt32(uint32_t value); 64 virtual uint64_t MutateUInt64(uint64_t value); 65 virtual float MutateFloat(float value); 66 virtual double MutateDouble(double value); 67 virtual bool MutateBool(bool value); 68 virtual size_t MutateEnum(size_t index, size_t item_count); 69 virtual std::string MutateString(const std::string& value, 70 size_t size_increase_hint); 71 72 // TODO(vitalybuka): Allow user to control proto level mutations: 73 // * Callbacks to recursive traversal. 74 // * Callbacks for particular proto level mutations. 75 random()76 RandomEngine* random() { return random_; } 77 78 private: 79 friend class FieldMutator; 80 friend class TestMutator; 81 void InitializeAndTrim(protobuf::Message* message, int max_depth); 82 void CrossOverImpl(const protobuf::Message& message1, 83 protobuf::Message* message2); 84 std::string MutateUtf8String(const std::string& value, 85 size_t size_increase_hint); 86 87 bool keep_initialized_ = true; 88 RandomEngine* random_; 89 }; 90 91 } // namespace protobuf_mutator 92 93 #endif // SRC_MUTATOR_H_ 94