blob: bbfd818914f0ce0389f1c6b354c61e123b463d47 [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 Buka432b5452016-12-09 14:42:09 -080015#ifndef PROTOBUF_MUTATOR_H_
16#define PROTOBUF_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
21#include <memory>
Vitaly Buka0e17fd72016-11-18 10:02:46 -080022#include <random>
Vitaly Buka00b61072016-10-19 16:22:51 -070023
Vitaly Buka0e17fd72016-11-18 10:02:46 -080024namespace google {
25namespace protobuf {
Vitaly Bukab5c12da2016-10-19 13:12:41 -070026class Message;
Vitaly Buka0e17fd72016-11-18 10:02:46 -080027}
28}
Vitaly Bukab5c12da2016-10-19 13:12:41 -070029
Vitaly Buka432b5452016-12-09 14:42:09 -080030namespace protobuf_mutator {
31
Vitaly Buka4af611d2016-12-03 18:57:32 -080032// Randomly makes incremental change in the given protobuf.
33// Usage example:
34// ProtobufMutator mutator(1);
35// MyMessage message;
36// message.ParseFromString(encoded_message);
Vitaly Buka4a6d6fc2016-12-16 14:21:37 -080037// mutator.Mutate(&message, 10000);
Vitaly Buka4af611d2016-12-03 18:57:32 -080038//
Vitaly Buka432b5452016-12-09 14:42:09 -080039// Class implements very basic mutations of fields. E.g. it just flips bits for
40// integers, floats and strings. Also it increases, decreases size of
41// strings only by one. For better results users should override
42// ProtobufMutator::Mutate* methods with more useful logic, e.g. using library
43// like libFuzzer.
Vitaly Bukab5c12da2016-10-19 13:12:41 -070044class ProtobufMutator {
45 public:
Vitaly Buka432b5452016-12-09 14:42:09 -080046 using RandomEngine = std::mt19937;
Vitaly Buka781853c2016-11-21 23:09:35 -080047
Vitaly Buka4af611d2016-12-03 18:57:32 -080048 // seed: value to initialize random number generator.
Vitaly Bukaba129722016-12-14 17:29:15 -080049 explicit ProtobufMutator(uint32_t seed);
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 Buka72019dc2016-12-14 19:17:24 -080057 void Mutate(google::protobuf::Message* message, size_t size_increase_hint);
Vitaly Buka4af611d2016-12-03 18:57:32 -080058
Vitaly Buka432b5452016-12-09 14:42:09 -080059 // TODO(vitalybuka): implement
Vitaly Buka0e17fd72016-11-18 10:02:46 -080060 bool CrossOver(const google::protobuf::Message& with,
61 google::protobuf::Message* message);
Vitaly Bukab5c12da2016-10-19 13:12:41 -070062
Vitaly Buka432b5452016-12-09 14:42:09 -080063 protected:
Vitaly Buka4af611d2016-12-03 18:57:32 -080064 virtual int32_t MutateInt32(int32_t value);
65 virtual int64_t MutateInt64(int64_t value);
66 virtual uint32_t MutateUInt32(uint32_t value);
67 virtual uint64_t MutateUInt64(uint64_t value);
68 virtual float MutateFloat(float value);
69 virtual double MutateDouble(double value);
70 virtual bool MutateBool(bool value);
71 virtual size_t MutateEnum(size_t index, size_t item_count);
72 virtual std::string MutateString(const std::string& value,
73 size_t allowed_growth);
74
Vitaly Buka432b5452016-12-09 14:42:09 -080075 // TODO(vitalybuka): Allow user to control proto level mutations:
Vitaly Buka4af611d2016-12-03 18:57:32 -080076 // * Callbacks to recursive traversal.
77 // * Callbacks for particular proto level mutations.
Vitaly Buka2cfe02b2016-11-18 16:34:09 -080078
Vitaly Bukab5c12da2016-10-19 13:12:41 -070079 private:
Vitaly Buka91ad7b02016-12-12 15:41:41 -080080 friend class MutateTransformation;
Vitaly Bukaba129722016-12-14 17:29:15 -080081 friend class TestProtobufMutator;
Vitaly Buka72019dc2016-12-14 19:17:24 -080082 void InitializeMessage(google::protobuf::Message* message, size_t max_depth);
Vitaly Buka4af611d2016-12-03 18:57:32 -080083
Vitaly Bukaba129722016-12-14 17:29:15 -080084 bool keep_initialized_ = true;
Vitaly Buka781853c2016-11-21 23:09:35 -080085 RandomEngine random_;
Vitaly Bukab5c12da2016-10-19 13:12:41 -070086};
87
Vitaly Buka432b5452016-12-09 14:42:09 -080088} // namespace protobuf_mutator
89
90#endif // PROTOBUF_MUTATOR_H_