From cf788596f480f194de120c49e5780c7a6dcd12f3 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Thu, 19 Dec 2019 03:46:37 +0000 Subject: [PATCH] fuzzing: Factor WireServer set up code out of frontend fuzzer This will make it easier to bring up other Dawn backend fuzzers that don't use the Null backend. Bug: dawn:295 Change-Id: I176b937722a63509cab620ac2a90098d87a6049c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/14623 Reviewed-by: Kai Ninomiya Reviewed-by: Corentin Wallez Commit-Queue: Austin Eng --- src/fuzzers/BUILD.gn | 26 ++++-- .../DawnWireServerAndFrontendFuzzer.cpp | 87 +++--------------- src/fuzzers/DawnWireServerFuzzer.cpp | 91 +++++++++++++++++++ src/fuzzers/DawnWireServerFuzzer.h | 32 +++++++ src/fuzzers/StandaloneFuzzerMain.cpp | 2 +- 5 files changed, 156 insertions(+), 82 deletions(-) create mode 100644 src/fuzzers/DawnWireServerFuzzer.cpp create mode 100644 src/fuzzers/DawnWireServerFuzzer.h diff --git a/src/fuzzers/BUILD.gn b/src/fuzzers/BUILD.gn index aea8fe622b..2b51d6e7a6 100644 --- a/src/fuzzers/BUILD.gn +++ b/src/fuzzers/BUILD.gn @@ -79,6 +79,20 @@ static_library("dawn_spirv_cross_fuzzer_common") { ] } +static_library("dawn_wire_server_fuzzer_common") { + sources = [ + "DawnWireServerFuzzer.cpp", + "DawnWireServerFuzzer.h", + ] + public_deps = [ + "${dawn_root}/:libdawn_native_static", + "${dawn_root}/:libdawn_wire_static", + "${dawn_root}/src/common", + "${dawn_root}/src/dawn:dawncpp", + "${dawn_root}/src/dawn:libdawn_proc", + ] +} + # TODO(rharrison): Remove asan_options once signal trap is no longer # needed. # Uses Dawn specific options and varies input data @@ -123,7 +137,7 @@ dawn_fuzzer_test("dawn_spvc_glsl_fast_fuzzer") { "DawnSPVCglslFastFuzzer.cpp", ] deps = [ - "${dawn_shaderc_dir}:libshaderc_spvc", + "${dawn_shaderc_dir}:libshaderc_spvc", ] } @@ -132,7 +146,7 @@ dawn_fuzzer_test("dawn_spvc_hlsl_fast_fuzzer") { "DawnSPVChlslFastFuzzer.cpp", ] deps = [ - "${dawn_shaderc_dir}:libshaderc_spvc", + "${dawn_shaderc_dir}:libshaderc_spvc", ] } @@ -141,7 +155,7 @@ dawn_fuzzer_test("dawn_spvc_msl_fast_fuzzer") { "DawnSPVCmslFastFuzzer.cpp", ] deps = [ - "${dawn_shaderc_dir}:libshaderc_spvc", + "${dawn_shaderc_dir}:libshaderc_spvc", ] } @@ -151,11 +165,7 @@ dawn_fuzzer_test("dawn_wire_server_and_frontend_fuzzer") { ] deps = [ - "${dawn_root}/:libdawn_native_static", - "${dawn_root}/:libdawn_wire_static", - "${dawn_root}/src/common", - "${dawn_root}/src/dawn:dawncpp", - "${dawn_root}/src/dawn:libdawn_proc", + ":dawn_wire_server_fuzzer_common", ] additional_configs = [ "${dawn_root}/src/common:dawn_internal" ] diff --git a/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp b/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp index ad904b7e6d..7911738314 100644 --- a/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp +++ b/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp @@ -12,85 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "DawnWireServerFuzzer.h" + #include "common/Assert.h" -#include "dawn/dawn_proc.h" -#include "dawn/webgpu_cpp.h" #include "dawn_native/DawnNative.h" -#include "dawn_wire/WireServer.h" - -#include - -class DevNull : public dawn_wire::CommandSerializer { - public: - void* GetCmdSpace(size_t size) override { - if (size > buf.size()) { - buf.resize(size); - } - return buf.data(); - } - bool Flush() override { - return true; - } - - private: - std::vector buf; -}; - -static WGPUProcDeviceCreateSwapChain originalDeviceCreateSwapChain = nullptr; - -WGPUSwapChain ErrorDeviceCreateSwapChain(WGPUDevice device, const WGPUSwapChainDescriptor*) { - WGPUSwapChainDescriptor desc; - desc.nextInChain = nullptr; - desc.label = nullptr; - // A 0 implementation will trigger a swapchain creation error. - desc.implementation = 0; - return originalDeviceCreateSwapChain(device, &desc); -} extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - DawnProcTable procs = dawn_native::GetProcs(); + return DawnWireServerFuzzer::Run(data, size, [](dawn_native::Instance* instance) { + instance->DiscoverDefaultAdapters(); - // Swapchains receive a pointer to an implementation. The fuzzer will pass garbage in so we - // intercept calls to create swapchains and make sure they always return error swapchains. - // This is ok for fuzzing because embedders of dawn_wire would always define their own - // swapchain handling. - originalDeviceCreateSwapChain = procs.deviceCreateSwapChain; - procs.deviceCreateSwapChain = ErrorDeviceCreateSwapChain; + std::vector adapters = instance->GetAdapters(); - dawnProcSetProcs(&procs); - - // Create an instance and find the null adapter to create a device with. - std::unique_ptr instance = std::make_unique(); - instance->DiscoverDefaultAdapters(); - - std::vector adapters = instance->GetAdapters(); - - wgpu::Device nullDevice; - for (dawn_native::Adapter adapter : adapters) { - if (adapter.GetBackendType() == dawn_native::BackendType::Null) { - nullDevice = wgpu::Device::Acquire(adapter.CreateDevice()); - break; + wgpu::Device nullDevice; + for (dawn_native::Adapter adapter : adapters) { + if (adapter.GetBackendType() == dawn_native::BackendType::Null) { + nullDevice = wgpu::Device::Acquire(adapter.CreateDevice()); + break; + } } - } - ASSERT(nullDevice.Get() != nullptr); - DevNull devNull; - dawn_wire::WireServerDescriptor serverDesc = {}; - serverDesc.device = nullDevice.Get(); - serverDesc.procs = &procs; - serverDesc.serializer = &devNull; - - std::unique_ptr wireServer(new dawn_wire::WireServer(serverDesc)); - - wireServer->HandleCommands(reinterpret_cast(data), size); - - // Fake waiting for all previous commands before destroying the server. - nullDevice.Tick(); - - // Destroy the server before the device because it needs to free all objects. - wireServer = nullptr; - nullDevice = nullptr; - instance = nullptr; - - return 0; + ASSERT(nullDevice.Get() != nullptr); + return nullDevice; + }); } diff --git a/src/fuzzers/DawnWireServerFuzzer.cpp b/src/fuzzers/DawnWireServerFuzzer.cpp new file mode 100644 index 0000000000..f7a19f1ab3 --- /dev/null +++ b/src/fuzzers/DawnWireServerFuzzer.cpp @@ -0,0 +1,91 @@ +// Copyright 2019 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "DawnWireServerFuzzer.h" + +#include "common/Assert.h" +#include "dawn/dawn_proc.h" +#include "dawn/webgpu_cpp.h" +#include "dawn_native/DawnNative.h" +#include "dawn_wire/WireServer.h" + +#include + +namespace { + + class DevNull : public dawn_wire::CommandSerializer { + public: + void* GetCmdSpace(size_t size) override { + if (size > buf.size()) { + buf.resize(size); + } + return buf.data(); + } + bool Flush() override { + return true; + } + + private: + std::vector buf; + }; + + WGPUProcDeviceCreateSwapChain sOriginalDeviceCreateSwapChain = nullptr; + + WGPUSwapChain ErrorDeviceCreateSwapChain(WGPUDevice device, const WGPUSwapChainDescriptor*) { + WGPUSwapChainDescriptor desc; + desc.nextInChain = nullptr; + desc.label = nullptr; + // A 0 implementation will trigger a swapchain creation error. + desc.implementation = 0; + return sOriginalDeviceCreateSwapChain(device, &desc); + } + +} // namespace + +int DawnWireServerFuzzer::Run(const uint8_t* data, size_t size, MakeDeviceFn MakeDevice) { + DawnProcTable procs = dawn_native::GetProcs(); + + // Swapchains receive a pointer to an implementation. The fuzzer will pass garbage in so we + // intercept calls to create swapchains and make sure they always return error swapchains. + // This is ok for fuzzing because embedders of dawn_wire would always define their own + // swapchain handling. + sOriginalDeviceCreateSwapChain = procs.deviceCreateSwapChain; + procs.deviceCreateSwapChain = ErrorDeviceCreateSwapChain; + + dawnProcSetProcs(&procs); + + std::unique_ptr instance = std::make_unique(); + wgpu::Device device = MakeDevice(instance.get()); + ASSERT(device); + + DevNull devNull; + dawn_wire::WireServerDescriptor serverDesc = {}; + serverDesc.device = device.Get(); + serverDesc.procs = &procs; + serverDesc.serializer = &devNull; + + std::unique_ptr wireServer(new dawn_wire::WireServer(serverDesc)); + + wireServer->HandleCommands(reinterpret_cast(data), size); + + // Fake waiting for all previous commands before destroying the server. + device.Tick(); + + // Destroy the server before the device because it needs to free all objects. + wireServer = nullptr; + device = nullptr; + instance = nullptr; + + return 0; +} diff --git a/src/fuzzers/DawnWireServerFuzzer.h b/src/fuzzers/DawnWireServerFuzzer.h new file mode 100644 index 0000000000..b4c011ebea --- /dev/null +++ b/src/fuzzers/DawnWireServerFuzzer.h @@ -0,0 +1,32 @@ +// Copyright 2019 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/webgpu_cpp.h" + +#include +#include + +namespace dawn_native { + + class Instance; + +} // namespace dawn_native + +namespace DawnWireServerFuzzer { + + using MakeDeviceFn = std::function; + + int Run(const uint8_t* data, size_t size, MakeDeviceFn MakeDevice); + +} // namespace DawnWireServerFuzzer diff --git a/src/fuzzers/StandaloneFuzzerMain.cpp b/src/fuzzers/StandaloneFuzzerMain.cpp index ba8d94b99d..9755e1d646 100644 --- a/src/fuzzers/StandaloneFuzzerMain.cpp +++ b/src/fuzzers/StandaloneFuzzerMain.cpp @@ -21,7 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); int main(int argc, char** argv) { if (argc != 2) { - std::cout << "Usage: [FILE]" << std::endl; + std::cout << "Usage: FILE" << std::endl; return 1; }