blob: 2661a034cb6108a465b2b012b6e441a8a94d02ca [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_SYS_FUZZING_COMMON_INPUT_H_
#define SRC_SYS_FUZZING_COMMON_INPUT_H_
#include <fuchsia/fuzzer/cpp/fidl.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include "src/lib/fxl/macros.h"
#include "src/sys/fuzzing/common/shared-memory.h"
namespace fuzzing {
using FidlInput = ::fuchsia::fuzzer::Input;
// Represents a single fuzzing input. A corpus is a collection of fuzzing inputs. Inputs are either
// provided as part of a seed corpus, or generated by mutating existing inputs.
class Input final {
public:
Input() = default;
Input(const std::initializer_list<uint8_t>& bytes) : Input(std::vector<uint8_t>(bytes)) {}
explicit Input(const std::vector<uint8_t>& bytes) : Input(bytes.data(), bytes.size()) {}
explicit Input(const std::string& bytes) : Input(bytes.c_str(), bytes.size()) {}
explicit Input(SharedMemory& shmem) : Input(shmem.data(), shmem.size()) {}
Input(Input&& other) noexcept { *this = std::move(other); }
~Input() = default;
Input& operator=(Input&& other) noexcept;
bool operator==(const Input& other) const;
bool operator!=(const Input& other) const { return !(*this == other); }
const uint8_t* data() const { return data_.get(); }
uint8_t* data() { return data_.get(); }
size_t size() const { return size_; }
size_t capacity() const { return capacity_; }
size_t num_features() const { return num_features_; }
void set_num_features(size_t num_features) { num_features_ = num_features; }
// Returns a hex string representation. Mostly used for testing/debugging.
std::string ToHex() const;
// Exchanges the internal state of this input with another.
void Swap(Input& other);
// Creates a copy of this input.
Input Duplicate() const;
// Makes this object a copy of the |other|.
void Duplicate(const Input& other);
// Ensures the input has at least the given |capacity|.
void Reserve(size_t capacity);
// Appends data to this input. The input must have sufficient remaining capacity for |size| bytes.
void Write(const void* data, size_t size);
void Write(uint8_t one_byte);
// Reserves capacity and sets the size of this input to |size| bytes. This method does NOT
// initialize the data, but can be used in conjunction with the |data()| accessor to write into
// the input. Returns the new size.
size_t Resize(size_t size);
// Truncates the input if larger than |max_size|. Returns the new size.
size_t Truncate(size_t max_size);
// Reduces the capacity of this input to its size. Returns the new size.
size_t ShrinkToFit();
// Removes all data from this input.
void Clear();
private:
Input(const void* data, size_t size) { Allocate(size, data, size); }
void Allocate(size_t capacity, const void* data = nullptr, size_t size = 0);
void StartExport(zx::socket* sender, FidlInput* receiver) const;
void FinishExport(const zx::socket& sender) const;
std::unique_ptr<uint8_t[]> data_;
size_t capacity_ = 0;
size_t size_ = 0;
size_t num_features_ = 0;
FXL_DISALLOW_COPY_AND_ASSIGN(Input);
};
} // namespace fuzzing
#endif // SRC_SYS_FUZZING_COMMON_INPUT_H_