blob: 4b7de23167421a66353456133b8fc9cbab8e1346 [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.
#include "src/sys/fuzzing/common/input.h"
#include <errno.h>
#include <lib/syslog/cpp/macros.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <zircon/status.h>
#include <algorithm>
#include <iomanip>
#include <sstream>
namespace fuzzing {
Input::Input(SharedMemory& shmem) {
if (auto status = shmem.Read(); status != ZX_OK) {
FX_LOGS(FATAL) << "Failed to read shared memory: " << zx_status_get_string(status);
}
Allocate(shmem.size(), shmem.data(), shmem.size());
}
void Input::Allocate(size_t capacity, const void* data, size_t size) {
if (capacity_ != capacity) {
capacity_ = capacity;
if (capacity_) {
data_ = std::make_unique<uint8_t[]>(capacity_);
} else {
data_.reset();
}
}
size_ = std::min(capacity, size);
if (data && size_) {
memcpy(data_.get(), data, size_);
}
}
Input& Input::operator=(Input&& other) noexcept {
data_ = std::move(other.data_);
capacity_ = other.capacity_;
size_ = other.size_;
num_features_ = other.num_features_;
other.data_.reset();
other.capacity_ = 0;
other.size_ = 0;
other.num_features_ = 0;
return *this;
}
int Input::Compare(const Input& other) const {
// Sort by size first: smaller before larger.
if (size_ < other.size_) {
return -1;
}
if (other.size_ < size_) {
return 1;
}
// All empty inputs are the same.
if (size_ == 0) {
return 0;
}
// Sort by features next: more before fewer.
if (other.num_features_ < num_features_) {
return -1;
}
if (num_features_ < other.num_features_) {
return 1;
}
// Sort by bytes last.
return memcmp(data_.get(), other.data_.get(), size_);
}
std::string Input::ToHex(bool truncate) const {
std::stringstream oss;
oss << std::hex;
auto* data = data_.get();
auto len = truncate ? std::min(size_, size_t(6)) : size_;
for (size_t i = 0; i < len; ++i) {
oss << std::setw(2) << std::setfill('0') << size_t(data[i]);
}
if (len != size_) {
oss << "...";
}
return oss.str();
}
void Input::Swap(Input& other) {
data_.swap(other.data_);
std::swap(capacity_, other.capacity_);
std::swap(size_, other.size_);
std::swap(num_features_, other.num_features_);
}
Input Input::Duplicate() const {
Input other;
other.Allocate(size_, data_.get(), size_);
other.num_features_ = num_features_;
return other;
}
void Input::Duplicate(const Input& other) {
Allocate(other.size_, other.data_.get(), other.size_);
num_features_ = other.num_features_;
}
void Input::Reserve(size_t capacity) {
if (capacity_ < capacity) {
auto tmp = std::move(data_);
Allocate(capacity, tmp.get(), size_);
}
}
void Input::Write(const void* data, size_t size) {
FX_DCHECK(size_ + size <= capacity_);
memcpy(&data_[size_], data, size);
size_ += size;
}
void Input::Write(uint8_t one_byte) {
FX_DCHECK(size_ < capacity_);
data_[size_++] = one_byte;
}
size_t Input::Resize(size_t size) {
Reserve(size);
size_ = size;
return size_;
}
size_t Input::Truncate(size_t max_size) {
size_ = std::min(size_, max_size);
return size_;
}
size_t Input::ShrinkToFit() {
if (size_ != capacity_) {
auto tmp = std::move(data_);
Allocate(size_, tmp.get(), size_);
}
return size_;
}
void Input::Clear() { size_ = 0; }
} // namespace fuzzing