From 1a15991c84a43381945cf5af171ddb6cef5406ae Mon Sep 17 00:00:00 2001 From: Brandon Jones Date: Thu, 11 Jun 2020 17:12:35 +0000 Subject: [PATCH] Add fuzzer for the d3d12 backend Adds harness for fuzzing the d3d12 backend with a WARP device. Bug: dawn:444 Change-Id: I3e5ca325b19eb8b6cfe53e4d833c5acbbd293a26 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22880 Commit-Queue: Brandon Jones Reviewed-by: Corentin Wallez --- src/dawn_native/d3d12/D3D12Error.cpp | 9 ++- src/dawn_native/d3d12/D3D12Error.h | 18 ++++- src/fuzzers/BUILD.gn | 78 +++++++------------ .../DawnWireServerAndD3D12BackendFuzzer.cpp | 44 +++++++++++ 4 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 src/fuzzers/DawnWireServerAndD3D12BackendFuzzer.cpp diff --git a/src/dawn_native/d3d12/D3D12Error.cpp b/src/dawn_native/d3d12/D3D12Error.cpp index d91d479c73..dfeaac0b44 100644 --- a/src/dawn_native/d3d12/D3D12Error.cpp +++ b/src/dawn_native/d3d12/D3D12Error.cpp @@ -17,7 +17,7 @@ #include namespace dawn_native { namespace d3d12 { - MaybeError CheckHRESULT(HRESULT result, const char* context) { + MaybeError CheckHRESULTImpl(HRESULT result, const char* context) { if (DAWN_LIKELY(SUCCEEDED(result))) { return {}; } @@ -31,11 +31,12 @@ namespace dawn_native { namespace d3d12 { } } - MaybeError CheckOutOfMemoryHRESULT(HRESULT result, const char* context) { - if (result == E_OUTOFMEMORY) { + MaybeError CheckOutOfMemoryHRESULTImpl(HRESULT result, const char* context) { + if (result == E_OUTOFMEMORY || result == E_FAKE_OUTOFMEMORY_ERROR_FOR_TESTING) { return DAWN_OUT_OF_MEMORY_ERROR(context); } - return CheckHRESULT(result, context); + + return CheckHRESULTImpl(result, context); } }} // namespace dawn_native::d3d12 diff --git a/src/dawn_native/d3d12/D3D12Error.h b/src/dawn_native/d3d12/D3D12Error.h index ed11a8c7c5..16ea4c4e83 100644 --- a/src/dawn_native/d3d12/D3D12Error.h +++ b/src/dawn_native/d3d12/D3D12Error.h @@ -17,14 +17,28 @@ #include #include "dawn_native/Error.h" +#include "dawn_native/ErrorInjector.h" namespace dawn_native { namespace d3d12 { + constexpr HRESULT E_FAKE_ERROR_FOR_TESTING = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xFF); + constexpr HRESULT E_FAKE_OUTOFMEMORY_ERROR_FOR_TESTING = + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xFE); + // Returns a success only if result of HResult is success - MaybeError CheckHRESULT(HRESULT result, const char* context); + MaybeError CheckHRESULTImpl(HRESULT result, const char* context); // Uses CheckRESULT but returns OOM specific error when recoverable. - MaybeError CheckOutOfMemoryHRESULT(HRESULT result, const char* context); + MaybeError CheckOutOfMemoryHRESULTImpl(HRESULT result, const char* context); + +#define CheckHRESULT(resultIn, contextIn) \ + ::dawn_native::d3d12::CheckHRESULTImpl( \ + INJECT_ERROR_OR_RUN(resultIn, E_FAKE_ERROR_FOR_TESTING), contextIn) +#define CheckOutOfMemoryHRESULT(resultIn, contextIn) \ + ::dawn_native::d3d12::CheckOutOfMemoryHRESULTImpl( \ + INJECT_ERROR_OR_RUN(resultIn, E_FAKE_OUTOFMEMORY_ERROR_FOR_TESTING, \ + E_FAKE_ERROR_FOR_TESTING), \ + contextIn) }} // namespace dawn_native::d3d12 diff --git a/src/fuzzers/BUILD.gn b/src/fuzzers/BUILD.gn index 71a6d88a96..c157b0a9ab 100644 --- a/src/fuzzers/BUILD.gn +++ b/src/fuzzers/BUILD.gn @@ -74,9 +74,7 @@ static_library("dawn_spirv_cross_fuzzer_common") { "DawnSPIRVCrossFuzzer.cpp", "DawnSPIRVCrossFuzzer.h", ] - public_deps = [ - "${dawn_shaderc_dir}:libshaderc_spvc", - ] + public_deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ] } static_library("dawn_wire_server_fuzzer_common") { @@ -98,12 +96,8 @@ static_library("dawn_wire_server_fuzzer_common") { # needed. # Uses Dawn specific options and varies input data dawn_fuzzer_test("dawn_spirv_cross_glsl_fast_fuzzer") { - sources = [ - "DawnSPIRVCrossGLSLFastFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] + sources = [ "DawnSPIRVCrossGLSLFastFuzzer.cpp" ] + deps = [ ":dawn_spirv_cross_fuzzer_common" ] asan_options = [ "allow_user_segv_handler=1" ] } @@ -111,12 +105,8 @@ dawn_fuzzer_test("dawn_spirv_cross_glsl_fast_fuzzer") { # needed. # Uses Dawn specific options and varies input data dawn_fuzzer_test("dawn_spirv_cross_hlsl_fast_fuzzer") { - sources = [ - "DawnSPIRVCrossHLSLFastFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] + sources = [ "DawnSPIRVCrossHLSLFastFuzzer.cpp" ] + deps = [ ":dawn_spirv_cross_fuzzer_common" ] asan_options = [ "allow_user_segv_handler=1" ] } @@ -124,62 +114,46 @@ dawn_fuzzer_test("dawn_spirv_cross_hlsl_fast_fuzzer") { # needed. # Uses Dawn specific options and varies input data dawn_fuzzer_test("dawn_spirv_cross_msl_fast_fuzzer") { - sources = [ - "DawnSPIRVCrossMSLFastFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] + sources = [ "DawnSPIRVCrossMSLFastFuzzer.cpp" ] + deps = [ ":dawn_spirv_cross_fuzzer_common" ] asan_options = [ "allow_user_segv_handler=1" ] } dawn_fuzzer_test("dawn_spvc_glsl_fast_fuzzer") { - sources = [ - "DawnSPVCglslFastFuzzer.cpp", - ] - deps = [ - "${dawn_shaderc_dir}:libshaderc_spvc", - ] + sources = [ "DawnSPVCglslFastFuzzer.cpp" ] + deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ] } dawn_fuzzer_test("dawn_spvc_hlsl_fast_fuzzer") { - sources = [ - "DawnSPVChlslFastFuzzer.cpp", - ] - deps = [ - "${dawn_shaderc_dir}:libshaderc_spvc", - ] + sources = [ "DawnSPVChlslFastFuzzer.cpp" ] + deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ] } dawn_fuzzer_test("dawn_spvc_msl_fast_fuzzer") { - sources = [ - "DawnSPVCmslFastFuzzer.cpp", - ] - deps = [ - "${dawn_shaderc_dir}:libshaderc_spvc", - ] + sources = [ "DawnSPVCmslFastFuzzer.cpp" ] + deps = [ "${dawn_shaderc_dir}:libshaderc_spvc" ] } dawn_fuzzer_test("dawn_wire_server_and_frontend_fuzzer") { - sources = [ - "DawnWireServerAndFrontendFuzzer.cpp", - ] + sources = [ "DawnWireServerAndFrontendFuzzer.cpp" ] - deps = [ - ":dawn_wire_server_fuzzer_common", - ] + deps = [ ":dawn_wire_server_fuzzer_common" ] + + additional_configs = [ "${dawn_root}/src/common:dawn_internal" ] +} + +dawn_fuzzer_test("dawn_wire_server_and_d3d12_backend_fuzzer") { + sources = [ "DawnWireServerAndD3D12BackendFuzzer.cpp" ] + + deps = [ ":dawn_wire_server_fuzzer_common" ] additional_configs = [ "${dawn_root}/src/common:dawn_internal" ] } dawn_fuzzer_test("dawn_wire_server_and_vulkan_backend_fuzzer") { - sources = [ - "DawnWireServerAndVulkanBackendFuzzer.cpp", - ] + sources = [ "DawnWireServerAndVulkanBackendFuzzer.cpp" ] - deps = [ - ":dawn_wire_server_fuzzer_common", - ] + deps = [ ":dawn_wire_server_fuzzer_common" ] additional_configs = [ "${dawn_root}/src/common:dawn_internal" ] } @@ -194,6 +168,8 @@ group("dawn_fuzzers") { ":dawn_spvc_glsl_fast_fuzzer", ":dawn_spvc_hlsl_fast_fuzzer", ":dawn_spvc_msl_fast_fuzzer", + ":dawn_wire_server_and_d3d12_backend_fuzzer", ":dawn_wire_server_and_frontend_fuzzer", + ":dawn_wire_server_and_vulkan_backend_fuzzer", ] } diff --git a/src/fuzzers/DawnWireServerAndD3D12BackendFuzzer.cpp b/src/fuzzers/DawnWireServerAndD3D12BackendFuzzer.cpp new file mode 100644 index 0000000000..79211361a8 --- /dev/null +++ b/src/fuzzers/DawnWireServerAndD3D12BackendFuzzer.cpp @@ -0,0 +1,44 @@ +// Copyright 2020 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 "dawn_native/DawnNative.h" +#include "testing/libfuzzer/libfuzzer_exports.h" + +extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { + return DawnWireServerFuzzer::Initialize(argc, argv); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + return DawnWireServerFuzzer::Run( + data, size, + [](dawn_native::Instance* instance) { + std::vector adapters = instance->GetAdapters(); + + wgpu::Device device; + for (dawn_native::Adapter adapter : adapters) { + wgpu::AdapterProperties properties; + adapter.GetProperties(&properties); + + if (properties.backendType == wgpu::BackendType::D3D12 && + properties.adapterType == wgpu::AdapterType::CPU) { + device = wgpu::Device::Acquire(adapter.CreateDevice()); + break; + } + } + return device; + }, + true /* supportsErrorInjection */); +}