blob: cd24d92163170b0c8584bdcf9578d8b8f4da2dfe [file] [log] [blame]
Vitaly Bukab5c12da2016-10-19 13:12:41 -07001// 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
Vitaly Bukaf90698f2017-03-01 15:46:58 -080015#ifndef SRC_MUTATOR_H_
16#define SRC_MUTATOR_H_
Vitaly Bukab5c12da2016-10-19 13:12:41 -070017
Vitaly Buka781853c2016-11-21 23:09:35 -080018#include <stddef.h>
19#include <stdint.h>
20
Allen-Webbc4fa5912018-09-07 15:53:30 -070021#include <functional>
Vitaly Buka781853c2016-11-21 23:09:35 -080022#include <memory>
Vitaly Buka0e17fd72016-11-18 10:02:46 -080023#include <random>
Vitaly Bukaf047a002017-01-12 23:57:00 -080024#include <string>
Allen-Webbc4fa5912018-09-07 15:53:30 -070025#include <unordered_map>
26#include <vector>
Vitaly Buka00b61072016-10-19 16:22:51 -070027
Vitaly Buka35df2e42017-02-25 01:17:25 -080028#include "port/protobuf.h"
Vitaly Bukaf62fe472017-03-01 23:05:15 -080029#include "src/random.h"
Vitaly Bukab5c12da2016-10-19 13:12:41 -070030
Vitaly Buka432b5452016-12-09 14:42:09 -080031namespace protobuf_mutator {
32
Vitaly Buka4af611d2016-12-03 18:57:32 -080033// Randomly makes incremental change in the given protobuf.
34// Usage example:
Vitaly Bukae79e0182017-03-01 16:02:14 -080035// protobuf_mutator::Mutator mutator(1);
Vitaly Buka4af611d2016-12-03 18:57:32 -080036// MyMessage message;
37// message.ParseFromString(encoded_message);
Vitaly Buka4a6d6fc2016-12-16 14:21:37 -080038// mutator.Mutate(&message, 10000);
Vitaly Buka4af611d2016-12-03 18:57:32 -080039//
Vitaly Buka432b5452016-12-09 14:42:09 -080040// 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
Vitaly Bukae79e0182017-03-01 16:02:14 -080043// protobuf_mutator::Mutator::Mutate* methods with more useful logic, e.g. using
44// library like libFuzzer.
45class Mutator {
Vitaly Bukab5c12da2016-10-19 13:12:41 -070046 public:
Vitaly Buka4af611d2016-12-03 18:57:32 -080047 // seed: value to initialize random number generator.
Vitaly Bukaf62fe472017-03-01 23:05:15 -080048 explicit Mutator(RandomEngine* random);
Vitaly Bukae79e0182017-03-01 16:02:14 -080049 virtual ~Mutator() = default;
Vitaly Buka781853c2016-11-21 23:09:35 -080050
Vitaly Buka4af611d2016-12-03 18:57:32 -080051 // message: message to mutate.
Vitaly Buka72019dc2016-12-14 19:17:24 -080052 // size_increase_hint: approximate number of bytes which can be added to the
53 // message. Method does not guarantee that real result size increase will be
54 // less than the value. It only changes probabilities of mutations which can
55 // cause size increase. Caller could repeat mutation if result was larger than
Vitaly Buka4af611d2016-12-03 18:57:32 -080056 // requested.
Vitaly Buka6c6dbbe2017-02-22 13:58:24 -080057 void Mutate(protobuf::Message* message, size_t size_increase_hint);
Vitaly Buka4af611d2016-12-03 18:57:32 -080058
Vitaly Bukaadfc27c2017-02-26 22:36:36 -080059 void CrossOver(const protobuf::Message& message1,
60 protobuf::Message* message2);
Vitaly Bukab5c12da2016-10-19 13:12:41 -070061
Allen-Webbc4fa5912018-09-07 15:53:30 -070062 // field: Descriptor of the field to apply the mutation to.
63 // mutation: callback function that applies the mutation.
64 static void RegisterCustomMutation(
65 const protobuf::FieldDescriptor* field,
66 std::function<void(protobuf::Message* message)> mutation);
67
Vitaly Buka432b5452016-12-09 14:42:09 -080068 protected:
Vitaly Bukab93a1462017-01-06 17:52:58 -080069 // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
Vitaly Buka4af611d2016-12-03 18:57:32 -080070 virtual int32_t MutateInt32(int32_t value);
71 virtual int64_t MutateInt64(int64_t value);
72 virtual uint32_t MutateUInt32(uint32_t value);
73 virtual uint64_t MutateUInt64(uint64_t value);
74 virtual float MutateFloat(float value);
75 virtual double MutateDouble(double value);
76 virtual bool MutateBool(bool value);
77 virtual size_t MutateEnum(size_t index, size_t item_count);
78 virtual std::string MutateString(const std::string& value,
Vitaly Buka5d013202017-02-24 16:50:11 -080079 size_t size_increase_hint);
Vitaly Buka4af611d2016-12-03 18:57:32 -080080
Vitaly Buka432b5452016-12-09 14:42:09 -080081 // TODO(vitalybuka): Allow user to control proto level mutations:
Vitaly Buka4af611d2016-12-03 18:57:32 -080082 // * Callbacks to recursive traversal.
83 // * Callbacks for particular proto level mutations.
Vitaly Buka2cfe02b2016-11-18 16:34:09 -080084
Vitaly Bukaf62fe472017-03-01 23:05:15 -080085 RandomEngine* random() { return random_; }
Vitaly Buka68e49ad2017-02-24 14:24:31 -080086
Allen-Webbc4fa5912018-09-07 15:53:30 -070087 static std::unordered_map<
88 const protobuf::FieldDescriptor*,
89 std::vector<std::function<void(protobuf::Message* message)>>>
90 custom_mutations_;
91
Vitaly Bukab5c12da2016-10-19 13:12:41 -070092 private:
Vitaly Buka5d013202017-02-24 16:50:11 -080093 friend class FieldMutator;
Vitaly Bukae79e0182017-03-01 16:02:14 -080094 friend class TestMutator;
Vitaly Bukae4eae602017-09-28 17:28:12 -070095 void InitializeAndTrim(protobuf::Message* message, int max_depth);
Vitaly Bukaadfc27c2017-02-26 22:36:36 -080096 void CrossOverImpl(const protobuf::Message& message1,
97 protobuf::Message* message2);
Vitaly Bukaaf8136f2017-06-09 16:40:12 -070098 std::string MutateUtf8String(const std::string& value,
99 size_t size_increase_hint);
Allen-Webbc4fa5912018-09-07 15:53:30 -0700100 bool ApplyCustomMutations(protobuf::Message* message,
101 const protobuf::FieldDescriptor* field);
Vitaly Bukaba129722016-12-14 17:29:15 -0800102 bool keep_initialized_ = true;
Vitaly Bukaf62fe472017-03-01 23:05:15 -0800103 RandomEngine* random_;
Vitaly Bukab5c12da2016-10-19 13:12:41 -0700104};
105
Vitaly Buka432b5452016-12-09 14:42:09 -0800106} // namespace protobuf_mutator
107
Vitaly Bukaf90698f2017-03-01 15:46:58 -0800108#endif // SRC_MUTATOR_H_