blob: 5e348f9d7a2cdba7c5360e16644c3a749608480d [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);
explicit Input(size_t size) : Input(std::vector<uint8_t>(size)) {}
Input(Input&& other) noexcept { *this = std::move(other); }
~Input() = default;
Input& operator=(Input&& other) noexcept;
inline bool operator==(const Input& other) const { return Compare(other) == 0; }
inline bool operator!=(const Input& other) const { return Compare(other) != 0; }
inline bool operator<(const Input& other) const { return Compare(other) < 0; }
inline bool operator>(const Input& other) const { return Compare(other) > 0; }
inline bool operator<=(const Input& other) const { return Compare(other) <= 0; }
inline bool operator>=(const Input& other) const { return Compare(other) >= 0; }
// This method allows easier printing by gTest.
friend std::ostream& operator<<(std::ostream& os, const Input& input) {
return os << input.ToHex(/* truncate */ false);
}
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. If the input is more than 6 bytes and |truncate|d, the
// returned string will be the first few bytes, followed by "...".
std::string ToHex(bool truncate = true) 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;
// Compares this input to some |other| input, and returns negative, zero, or positive depending on
// whether this input should be considered less than, equal to, or greater than the other input
// when sorting. The defined sort order is "smaller size, then more features, then byte-by-byte".
//
// Returns negative if this input is shorter than |other|, or the same length but with more
// features than |other|, or the same length with the same number of features but the first
// non-matching byte is less than the corresponding byte in |other|.
//
// Returns postive if this input is longer than |other|, or the same length but with fewer
// features than |other|, or the same length with the same number of features but the first
// non-matching byte is greater than the corresponding byte in |other|.
//
// Returns zero if this input has the same bytes as |other|.
int Compare(const Input& other) 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_