Commit dad67377 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] "Vectorize" fuzzer

Instead of passing {uint8_t*, size_t} pairs as arguments, pass
{Vector<uint8_t>}. This is less error prone and {Vector} provides some
helpful methods.

R=ahaas@chromium.org

Bug: v8:7754
Change-Id: I7469054774618e0bd5c9d38501759b1b2c51d104
Reviewed-on: https://chromium-review.googlesource.com/1134773Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54406}
parent 03558130
...@@ -123,11 +123,18 @@ class Vector { ...@@ -123,11 +123,18 @@ class Vector {
length_ = 0; length_ = 0;
} }
inline Vector<T> operator+(size_t offset) { Vector<T> operator+(size_t offset) {
DCHECK_LE(offset, length_); DCHECK_LE(offset, length_);
return Vector<T>(start_ + offset, length_ - offset); return Vector<T>(start_ + offset, length_ - offset);
} }
Vector<T> operator+=(size_t offset) {
DCHECK_LE(offset, length_);
start_ += offset;
length_ -= offset;
return *this;
}
// Implicit conversion from Vector<T> to Vector<const T>. // Implicit conversion from Vector<T> to Vector<const T>.
inline operator Vector<const T>() { return Vector<const T>::cast(*this); } inline operator Vector<const T>() { return Vector<const T>::cast(*this); }
......
...@@ -20,14 +20,14 @@ namespace fuzzer { ...@@ -20,14 +20,14 @@ namespace fuzzer {
class WasmCodeFuzzer : public WasmExecutionFuzzer { class WasmCodeFuzzer : public WasmExecutionFuzzer {
bool GenerateModule( bool GenerateModule(
Isolate* isolate, Zone* zone, const uint8_t* data, size_t size, Isolate* isolate, Zone* zone, Vector<const uint8_t> data,
ZoneBuffer& buffer, int32_t& num_args, ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmValue[]>& interpreter_args, std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) override { std::unique_ptr<Handle<Object>[]>& compiler_args) override {
TestSignatures sigs; TestSignatures sigs;
WasmModuleBuilder builder(zone); WasmModuleBuilder builder(zone);
WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
f->EmitCode(data, static_cast<uint32_t>(size)); f->EmitCode(data.start(), static_cast<uint32_t>(data.size()));
uint8_t end_opcode = kExprEnd; uint8_t end_opcode = kExprEnd;
f->EmitCode(&end_opcode, 1); f->EmitCode(&end_opcode, 1);
builder.AddExport(CStrVector("main"), f); builder.AddExport(CStrVector("main"), f);
...@@ -46,7 +46,7 @@ class WasmCodeFuzzer : public WasmExecutionFuzzer { ...@@ -46,7 +46,7 @@ class WasmCodeFuzzer : public WasmExecutionFuzzer {
}; };
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return WasmCodeFuzzer().FuzzWasmModule(data, size); return WasmCodeFuzzer().FuzzWasmModule({data, size});
} }
} // namespace fuzzer } // namespace fuzzer
......
...@@ -34,35 +34,28 @@ constexpr int kMaxFunctions = 4; ...@@ -34,35 +34,28 @@ constexpr int kMaxFunctions = 4;
constexpr int kMaxGlobals = 64; constexpr int kMaxGlobals = 64;
class DataRange { class DataRange {
const uint8_t* data_; Vector<const uint8_t> data_;
size_t size_;
public: public:
DataRange(const uint8_t* data, size_t size) : data_(data), size_(size) {} explicit DataRange(Vector<const uint8_t> data) : data_(data) {}
// Don't accidentally pass DataRange by value. This will reuse bytes and might // Don't accidentally pass DataRange by value. This will reuse bytes and might
// lead to OOM because the end might not be reached. // lead to OOM because the end might not be reached.
// Define move constructor and move assignment, disallow copy constructor and // Define move constructor and move assignment, disallow copy constructor and
// copy assignment (below). // copy assignment (below).
DataRange(DataRange&& other) : DataRange(other.data_, other.size_) { DataRange(DataRange&& other) : DataRange(other.data_) { other.data_ = {}; }
other.data_ = nullptr;
other.size_ = 0;
}
DataRange& operator=(DataRange&& other) { DataRange& operator=(DataRange&& other) {
data_ = other.data_; data_ = other.data_;
size_ = other.size_; other.data_ = {};
other.data_ = nullptr;
other.size_ = 0;
return *this; return *this;
} }
size_t size() const { return size_; } size_t size() const { return data_.size(); }
DataRange split() { DataRange split() {
uint16_t num_bytes = get<uint16_t>() % std::max(size_t{1}, size_); uint16_t num_bytes = get<uint16_t>() % std::max(size_t{1}, data_.size());
DataRange split(data_, num_bytes); DataRange split(data_.SubVector(0, num_bytes));
data_ += num_bytes; data_ += num_bytes;
size_ -= num_bytes;
return split; return split;
} }
...@@ -73,11 +66,10 @@ class DataRange { ...@@ -73,11 +66,10 @@ class DataRange {
// okay if we don't have a full four bytes available, we'll just use what // okay if we don't have a full four bytes available, we'll just use what
// we have. We aren't concerned about endianness because we are generating // we have. We aren't concerned about endianness because we are generating
// arbitrary expressions. // arbitrary expressions.
const size_t num_bytes = std::min(sizeof(T), size_); const size_t num_bytes = std::min(sizeof(T), data_.size());
T result = T(); T result = T();
memcpy(&result, data_, num_bytes); memcpy(&result, data_.start(), num_bytes);
data_ += num_bytes; data_ += num_bytes;
size_ -= num_bytes;
return result; return result;
} }
...@@ -751,7 +743,7 @@ FunctionSig* GenerateSig(Zone* zone, DataRange& data) { ...@@ -751,7 +743,7 @@ FunctionSig* GenerateSig(Zone* zone, DataRange& data) {
class WasmCompileFuzzer : public WasmExecutionFuzzer { class WasmCompileFuzzer : public WasmExecutionFuzzer {
bool GenerateModule( bool GenerateModule(
Isolate* isolate, Zone* zone, const uint8_t* data, size_t size, Isolate* isolate, Zone* zone, Vector<const uint8_t> data,
ZoneBuffer& buffer, int32_t& num_args, ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmValue[]>& interpreter_args, std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) override { std::unique_ptr<Handle<Object>[]>& compiler_args) override {
...@@ -759,7 +751,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer { ...@@ -759,7 +751,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
WasmModuleBuilder builder(zone); WasmModuleBuilder builder(zone);
DataRange range(data, static_cast<uint32_t>(size)); DataRange range(data);
std::vector<FunctionSig*> function_signatures; std::vector<FunctionSig*> function_signatures;
function_signatures.push_back(sigs.i_iii()); function_signatures.push_back(sigs.i_iii());
...@@ -819,7 +811,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer { ...@@ -819,7 +811,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
constexpr bool require_valid = true; constexpr bool require_valid = true;
return WasmCompileFuzzer().FuzzWasmModule(data, size, require_valid); return WasmCompileFuzzer().FuzzWasmModule({data, size}, require_valid);
} }
} // namespace fuzzer } // namespace fuzzer
......
...@@ -247,7 +247,7 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes, ...@@ -247,7 +247,7 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes,
os << "})();\n"; os << "})();\n";
} }
int WasmExecutionFuzzer::FuzzWasmModule(const uint8_t* data, size_t size, int WasmExecutionFuzzer::FuzzWasmModule(Vector<const uint8_t> data,
bool require_valid) { bool require_valid) {
v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get(); v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
v8::Isolate* isolate = support->GetIsolate(); v8::Isolate* isolate = support->GetIsolate();
...@@ -269,7 +269,7 @@ int WasmExecutionFuzzer::FuzzWasmModule(const uint8_t* data, size_t size, ...@@ -269,7 +269,7 @@ int WasmExecutionFuzzer::FuzzWasmModule(const uint8_t* data, size_t size,
int32_t num_args = 0; int32_t num_args = 0;
std::unique_ptr<WasmValue[]> interpreter_args; std::unique_ptr<WasmValue[]> interpreter_args;
std::unique_ptr<Handle<Object>[]> compiler_args; std::unique_ptr<Handle<Object>[]> compiler_args;
if (!GenerateModule(i_isolate, &zone, data, size, buffer, num_args, if (!GenerateModule(i_isolate, &zone, data, buffer, num_args,
interpreter_args, compiler_args)) { interpreter_args, compiler_args)) {
return 0; return 0;
} }
......
...@@ -32,12 +32,11 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes, ...@@ -32,12 +32,11 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes,
class WasmExecutionFuzzer { class WasmExecutionFuzzer {
public: public:
virtual ~WasmExecutionFuzzer() {} virtual ~WasmExecutionFuzzer() {}
int FuzzWasmModule(const uint8_t* data, size_t size, int FuzzWasmModule(Vector<const uint8_t> data, bool require_valid = false);
bool require_valid = false);
protected: protected:
virtual bool GenerateModule( virtual bool GenerateModule(
Isolate* isolate, Zone* zone, const uint8_t* data, size_t size, Isolate* isolate, Zone* zone, Vector<const uint8_t> data,
ZoneBuffer& buffer, int32_t& num_args, ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmValue[]>& interpreter_args, std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) = 0; std::unique_ptr<Handle<Object>[]>& compiler_args) = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment