blob: 47139bdf0b91b80ef36bc9b31af379f7d8b8b4bc [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
21#include <memory>
Vitaly Buka0e17fd72016-11-18 10:02:46 -080022#include <random>
Vitaly Bukaf047a002017-01-12 23:57:00 -080023#include <string>
Vitaly Buka00b61072016-10-19 16:22:51 -070024
Vitaly Buka35df2e42017-02-25 01:17:25 -080025#include "port/protobuf.h"
Vitaly Bukaf62fe472017-03-01 23:05:15 -080026#include "src/random.h"
Vitaly Bukab5c12da2016-10-19 13:12:41 -070027
Vitaly Buka432b5452016-12-09 14:42:09 -080028namespace protobuf_mutator {
29
Vitaly Buka4af611d2016-12-03 18:57:32 -080030// Randomly makes incremental change in the given protobuf.
31// Usage example:
Vitaly Bukae79e0182017-03-01 16:02:14 -080032// protobuf_mutator::Mutator mutator(1);
Vitaly Buka4af611d2016-12-03 18:57:32 -080033// MyMessage message;
34// message.ParseFromString(encoded_message);
Vitaly Buka4a6d6fc2016-12-16 14:21:37 -080035// mutator.Mutate(&message, 10000);
Vitaly Buka4af611d2016-12-03 18:57:32 -080036//
Vitaly Buka432b5452016-12-09 14:42:09 -080037// 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
Vitaly Bukae79e0182017-03-01 16:02:14 -080040// protobuf_mutator::Mutator::Mutate* methods with more useful logic, e.g. using
41// library like libFuzzer.
42class Mutator {
Vitaly Bukab5c12da2016-10-19 13:12:41 -070043 public:
Vitaly Buka4af611d2016-12-03 18:57:32 -080044 // seed: value to initialize random number generator.
Vitaly Bukaf62fe472017-03-01 23:05:15 -080045 explicit Mutator(RandomEngine* random);
Vitaly Bukae79e0182017-03-01 16:02:14 -080046 virtual ~Mutator() = default;
Vitaly Buka781853c2016-11-21 23:09:35 -080047
Vitaly Buka4af611d2016-12-03 18:57:32 -080048 // message: message to mutate.
Vitaly Buka72019dc2016-12-14 19:17:24 -080049 // 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
Vitaly Buka4af611d2016-12-03 18:57:32 -080053 // requested.
Vitaly Buka6c6dbbe2017-02-22 13:58:24 -080054 void Mutate(protobuf::Message* message, size_t size_increase_hint);
Vitaly Buka4af611d2016-12-03 18:57:32 -080055
Vitaly Bukaadfc27c2017-02-26 22:36:36 -080056 void CrossOver(const protobuf::Message& message1,
57 protobuf::Message* message2);
Vitaly Bukab5c12da2016-10-19 13:12:41 -070058
Vitaly Buka432b5452016-12-09 14:42:09 -080059 protected:
Vitaly Bukab93a1462017-01-06 17:52:58 -080060 // TODO(vitalybuka): Consider to replace with single mutate (uint8_t*, size).
Vitaly Buka4af611d2016-12-03 18:57:32 -080061 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,
Vitaly Buka5d013202017-02-24 16:50:11 -080070 size_t size_increase_hint);
Vitaly Buka4af611d2016-12-03 18:57:32 -080071
Vitaly Buka432b5452016-12-09 14:42:09 -080072 // TODO(vitalybuka): Allow user to control proto level mutations:
Vitaly Buka4af611d2016-12-03 18:57:32 -080073 // * Callbacks to recursive traversal.
74 // * Callbacks for particular proto level mutations.
Vitaly Buka2cfe02b2016-11-18 16:34:09 -080075
Vitaly Bukaf62fe472017-03-01 23:05:15 -080076 RandomEngine* random() { return random_; }
Vitaly Buka68e49ad2017-02-24 14:24:31 -080077
Vitaly Bukab5c12da2016-10-19 13:12:41 -070078 private:
Vitaly Buka5d013202017-02-24 16:50:11 -080079 friend class FieldMutator;
Vitaly Bukae79e0182017-03-01 16:02:14 -080080 friend class TestMutator;
Vitaly Bukae4eae602017-09-28 17:28:12 -070081 void InitializeAndTrim(protobuf::Message* message, int max_depth);
Vitaly Bukaadfc27c2017-02-26 22:36:36 -080082 void CrossOverImpl(const protobuf::Message& message1,
83 protobuf::Message* message2);
Vitaly Bukaaf8136f2017-06-09 16:40:12 -070084 std::string MutateUtf8String(const std::string& value,
85 size_t size_increase_hint);
Vitaly Buka4af611d2016-12-03 18:57:32 -080086
Vitaly Bukaba129722016-12-14 17:29:15 -080087 bool keep_initialized_ = true;
Vitaly Bukaf62fe472017-03-01 23:05:15 -080088 RandomEngine* random_;
Vitaly Bukab5c12da2016-10-19 13:12:41 -070089};
90
Vitaly Buka432b5452016-12-09 14:42:09 -080091} // namespace protobuf_mutator
92
Vitaly Bukaf90698f2017-03-01 15:46:58 -080093#endif // SRC_MUTATOR_H_