From fbeca676d409ec19572e3299288f4010c2ee8fd5 Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Mon, 19 Nov 2018 19:20:08 +0000 Subject: [PATCH] Tighten when signal trap is used in SPIRV-Cross fuzzers Due the jump within the signal trap used in these fuzzers, local scope allocations cannot occur while the signal trap is on, otherwise there is a possibility of leaks. This CL rewrites how the code under test is run, so that the potentially aborting code is tightly wrapped by signal trap without any local scope allocations. BUG=chromium:906416 Change-Id: Ie52647433dcac57e3ea065d5bdcb6e14c5929494 Reviewed-on: https://dawn-review.googlesource.com/c/2521 Commit-Queue: Ryan Harrison Reviewed-by: Corentin Wallez --- src/fuzzers/DawnSPIRVCrossFuzzer.cpp | 33 +++++++++----------- src/fuzzers/DawnSPIRVCrossFuzzer.h | 8 +++-- src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp | 15 ++++++--- src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp | 16 +++++++--- src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp | 17 +++++++--- src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp | 17 +++++++--- src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp | 14 ++++++--- src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp | 14 ++++++--- 8 files changed, 87 insertions(+), 47 deletions(-) diff --git a/src/fuzzers/DawnSPIRVCrossFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossFuzzer.cpp index 55b340a7fe..c37b2156ad 100644 --- a/src/fuzzers/DawnSPIRVCrossFuzzer.cpp +++ b/src/fuzzers/DawnSPIRVCrossFuzzer.cpp @@ -52,29 +52,32 @@ namespace { namespace DawnSPIRVCrossFuzzer { - int Run(const uint8_t* data, size_t size, std::function)> task) { - if (!data || size < 1) - return 0; - - std::vector input(data, data + (4 * (size / 4))); - + void ExecuteWithSignalTrap(std::function exec) { BeginSIGABRTTrap(); // On the first pass through setjmp will return 0, if returning here // from the longjmp in the signal handler it will return 1. if (setjmp(jump_buffer) == 0) { - task(input); + exec(); } EndSIGABRTTrap(); + } + int Run(const uint8_t* data, size_t size, Task task) { + if (!data || size < 1) + return 0; + + size_t sizeInU32 = size / sizeof(uint32_t); + const uint32_t* u32Data = reinterpret_cast(data); + std::vector input(u32Data, u32Data + sizeInU32); + + task(input); return 0; } template - int RunWithOptions(const uint8_t* data, - size_t size, - std::function, Options)> task) { + int RunWithOptions(const uint8_t* data, size_t size, TaskWithOptions task) { if (!data || size < sizeof(Options) + 1) return 0; @@ -84,15 +87,7 @@ namespace DawnSPIRVCrossFuzzer { std::vector input(data, data + (4 * (size / 4))); - BeginSIGABRTTrap(); - - // On the first pass through setjmp will return 0, if returning here - // from the longjmp in the signal handler it will return 1. - if (setjmp(jump_buffer) == 0) { - task(input, options); - } - - EndSIGABRTTrap(); + task(input, options); return 0; } diff --git a/src/fuzzers/DawnSPIRVCrossFuzzer.h b/src/fuzzers/DawnSPIRVCrossFuzzer.h index d6cebbc845..47e30400ac 100644 --- a/src/fuzzers/DawnSPIRVCrossFuzzer.h +++ b/src/fuzzers/DawnSPIRVCrossFuzzer.h @@ -26,9 +26,13 @@ namespace DawnSPIRVCrossFuzzer { spirv_cross::CompilerHLSL::Options hlsl; }; - using Task = std::function)>; + using Task = std::function&)>; template - using TaskWithOptions = std::function, Options)>; + using TaskWithOptions = std::function&, Options)>; + + // Used to wrap code that may fire a SIGABRT. Do not allocate anything local within |exec|, as + // it is not guaranteed to return. + void ExecuteWithSignalTrap(std::function exec); // Used to fuzz by mutating the input data, but with fixed options to the compiler int Run(const uint8_t* data, size_t size, Task task); diff --git a/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp index 1959612d03..53b06cf393 100644 --- a/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp +++ b/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp @@ -20,15 +20,22 @@ namespace { - int GLSLFastFuzzTask(std::vector input) { - spirv_cross::CompilerGLSL compiler(input); + int GLSLFastFuzzTask(const std::vector& input) { + std::unique_ptr compiler; + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { + compiler = std::make_unique(input); + }); + if (compiler == nullptr) { + return 0; + } // Using the options that are used by Dawn, they appear in ShaderModuleGL.cpp spirv_cross::CompilerGLSL::Options options; options.version = 440; - compiler.set_common_options(options); + compiler->set_common_options(options); + + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); - std::string result = compiler.compile(); return 0; } diff --git a/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp index 9784670890..2ff9fefb7d 100644 --- a/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp +++ b/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp @@ -20,11 +20,19 @@ namespace { - int GLSLFullFuzzTask(std::vector input, spirv_cross::CompilerGLSL::Options options) { - spirv_cross::CompilerGLSL compiler(input); - compiler.set_common_options(options); + int GLSLFullFuzzTask(const std::vector& input, + spirv_cross::CompilerGLSL::Options options) { + std::unique_ptr compiler; + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { + compiler = std::make_unique(input); + }); + if (compiler == nullptr) { + return 0; + } - std::string result = compiler.compile(); + compiler->set_common_options(options); + + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); return 0; } diff --git a/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp index 85e83e7487..9d9cd9d24e 100644 --- a/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp +++ b/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp @@ -22,20 +22,27 @@ namespace { - int FuzzTask(std::vector input) { - spirv_cross::CompilerHLSL compiler(input); + int FuzzTask(const std::vector& input) { + std::unique_ptr compiler; + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { + compiler = std::make_unique(input); + }); + if (compiler == nullptr) { + return 0; + } // Using the options that are used by Dawn, they appear in ShaderModuleD3D12.cpp spirv_cross::CompilerGLSL::Options options_glsl; options_glsl.vertex.fixup_clipspace = true; options_glsl.vertex.flip_vert_y = true; - compiler.set_common_options(options_glsl); + compiler->set_common_options(options_glsl); spirv_cross::CompilerHLSL::Options options_hlsl; options_hlsl.shader_model = 51; - compiler.set_hlsl_options(options_hlsl); + compiler->set_hlsl_options(options_hlsl); + + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); - std::string result = compiler.compile(); return 0; } diff --git a/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp index 1985d2afb0..2433752ca4 100644 --- a/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp +++ b/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp @@ -21,13 +21,20 @@ #include "spirv-cross/spirv_hlsl.hpp" namespace { - int FuzzTask(std::vector input, DawnSPIRVCrossFuzzer::CombinedOptions options) { - spirv_cross::CompilerHLSL compiler(input); + int FuzzTask(const std::vector& input, + DawnSPIRVCrossFuzzer::CombinedOptions options) { + std::unique_ptr compiler; + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { + compiler = std::make_unique(input); + }); + if (compiler == nullptr) { + return 0; + } - compiler.set_common_options(options.glsl); - compiler.set_hlsl_options(options.hlsl); + compiler->set_common_options(options.glsl); + compiler->set_hlsl_options(options.hlsl); - std::string result = compiler.compile(); + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); return 0; } diff --git a/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp index 349d770dc5..4b0da62e27 100644 --- a/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp +++ b/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp @@ -22,15 +22,21 @@ namespace { - int FuzzTask(std::vector input) { - spirv_cross::CompilerMSL compiler(input); + int FuzzTask(const std::vector& input) { + std::unique_ptr compiler; + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap( + [&compiler, input]() { compiler = std::make_unique(input); }); + if (compiler == nullptr) { + return 0; + } // Using the options that are used by Dawn, they appear in ShaderModuleMTL.mm spirv_cross::CompilerGLSL::Options options; options.vertex.flip_vert_y = true; - compiler.spirv_cross::CompilerGLSL::set_common_options(options); + compiler->spirv_cross::CompilerGLSL::set_common_options(options); + + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); - std::string result = compiler.compile(); return 0; } diff --git a/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp b/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp index 1aaf3b0f6f..7b66edd93c 100644 --- a/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp +++ b/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp @@ -22,12 +22,18 @@ namespace { - int FuzzTask(std::vector input, spirv_cross::CompilerGLSL::Options options) { - spirv_cross::CompilerMSL compiler(input); + int FuzzTask(const std::vector& input, spirv_cross::CompilerGLSL::Options options) { + std::unique_ptr compiler; + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap( + [&compiler, input]() { compiler = std::make_unique(input); }); + if (compiler == nullptr) { + return 0; + } - compiler.spirv_cross::CompilerGLSL::set_common_options(options); + compiler->spirv_cross::CompilerGLSL::set_common_options(options); + + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); - std::string result = compiler.compile(); return 0; }