diff --git a/BUILD.gn b/BUILD.gn index 12efda6ba6..cc0fc287c1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -17,9 +17,6 @@ import("scripts/dawn_features.gni") import("//build_overrides/build.gni") import("//testing/test.gni") -if (build_with_chromium) { - import("//testing/libfuzzer/fuzzer_test.gni") -} ############################################################################### # Template to wrap the Dawn code generator @@ -948,100 +945,16 @@ if (dawn_standalone) { ############################################################################### # Fuzzers ############################################################################### -if (build_with_chromium) { - group("dawn_fuzzers") { - testonly = true - deps = [ - ":dawn_spirv_cross_glsl_fast_fuzzer", - ":dawn_spirv_cross_glsl_full_fuzzer", - ":dawn_spirv_cross_hlsl_fast_fuzzer", - ":dawn_spirv_cross_hlsl_full_fuzzer", - ":dawn_spirv_cross_msl_fast_fuzzer", - ":dawn_spirv_cross_msl_full_fuzzer", - ] - } - static_library("dawn_spirv_cross_fuzzer_common") { - sources = [ - "src/fuzzers/DawnSPIRVCrossFuzzer.cpp", - "src/fuzzers/DawnSPIRVCrossFuzzer.h", - ] - public_deps = [ - "third_party:spirv_cross", - ] - } - - # Uses Dawn specific options and varies input data - fuzzer_test("dawn_spirv_cross_glsl_fast_fuzzer") { - sources = [ - "src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] - } - - # Varies bother the options and input data - fuzzer_test("dawn_spirv_cross_glsl_full_fuzzer") { - sources = [ - "src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] - } - - # Uses Dawn specific options and varies input data - fuzzer_test("dawn_spirv_cross_hlsl_fast_fuzzer") { - sources = [ - "src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] - } - - # Varies bother the options and input data - fuzzer_test("dawn_spirv_cross_hlsl_full_fuzzer") { - sources = [ - "src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] - } - - # Uses Dawn specific options and varies input data - fuzzer_test("dawn_spirv_cross_msl_fast_fuzzer") { - sources = [ - "src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] - } - - # Varies bother the options and input data - fuzzer_test("dawn_spirv_cross_msl_full_fuzzer") { - sources = [ - "src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp", - ] - deps = [ - ":dawn_spirv_cross_fuzzer_common", - ] - } - - fuzzer_test("dawn_wire_server_and_frontend_fuzzer") { - sources = [ - "src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp", - ] - - deps = [ - ":libdawn", - ":libdawn_native", - ":libdawn_wire", - ] - - additional_configs = [ ":dawn_shared_library_public" ] - } +group("dawn_fuzzers") { + testonly = true + deps = [ + "src/fuzzers:dawn_spirv_cross_glsl_fast_fuzzer", + "src/fuzzers:dawn_spirv_cross_glsl_full_fuzzer", + "src/fuzzers:dawn_spirv_cross_hlsl_fast_fuzzer", + "src/fuzzers:dawn_spirv_cross_hlsl_full_fuzzer", + "src/fuzzers:dawn_spirv_cross_msl_fast_fuzzer", + "src/fuzzers:dawn_spirv_cross_msl_full_fuzzer", + "src/fuzzers:dawn_wire_server_and_frontend_fuzzer", + ] } diff --git a/src/fuzzers/BUILD.gn b/src/fuzzers/BUILD.gn new file mode 100644 index 0000000000..9680d6e3b5 --- /dev/null +++ b/src/fuzzers/BUILD.gn @@ -0,0 +1,150 @@ +# Copyright 2018 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. + +import("//build_overrides/build.gni") + +dawn_top_level = "../.." + +# We only have libfuzzer in Chromium builds but if we build fuzzer targets only +# there, we would risk breaking fuzzer targets all the time when making changes +# to Dawn. To avoid that, we make fuzzer targets compile in standalone builds +# as well with a dawn_fuzzer_test target that acts like Chromium's fuzzer_test. +# +# The standalone fuzzer targets are able to run a single fuzzer input which +# could help reproduce fuzzer crashes more easily because you don't need a +# whole Chromium checkout. + +if (build_with_chromium) { + import("//testing/libfuzzer/fuzzer_test.gni") + + # In Chromium build we just proxy everything to the real fuzzer_test + template("dawn_fuzzer_test") { + fuzzer_test(target_name) { + forward_variables_from(invoker, "*") + } + } +} else { + import("//testing/test.gni") + + # In standalone build we do something similar to fuzzer_test. + template("dawn_fuzzer_test") { + test(target_name) { + forward_variables_from(invoker, + [ + "cflags", + "cflags_cc", + "check_includes", + "defines", + "deps", + "include_dirs", + "sources", + ]) + + if (!defined(configs)) { + configs = [] + } + + # Weirdly fuzzer_test uses a special variable for additional configs. + if (defined(invoker.additional_configs)) { + configs += invoker.additional_configs + } + + sources += [ "StandaloneFuzzerMain.cpp" ] + } + } +} + +static_library("dawn_spirv_cross_fuzzer_common") { + sources = [ + "DawnSPIRVCrossFuzzer.cpp", + "DawnSPIRVCrossFuzzer.h", + ] + public_deps = [ + "${dawn_top_level}/third_party:spirv_cross", + ] +} + +# 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", + ] +} + +# Varies bother the options and input data +dawn_fuzzer_test("dawn_spirv_cross_glsl_full_fuzzer") { + sources = [ + "DawnSPIRVCrossGLSLFullFuzzer.cpp", + ] + deps = [ + ":dawn_spirv_cross_fuzzer_common", + ] +} + +# Uses Dawn specific options and varies input data +dawn_fuzzer_test("dawn_spirv_cross_hlsl_fast_fuzzer") { + sources = [ + "DawnSPIRVCrossGLSLFastFuzzer.cpp", + ] + deps = [ + ":dawn_spirv_cross_fuzzer_common", + ] +} + +# Varies bother the options and input data +dawn_fuzzer_test("dawn_spirv_cross_hlsl_full_fuzzer") { + sources = [ + "DawnSPIRVCrossGLSLFullFuzzer.cpp", + ] + deps = [ + ":dawn_spirv_cross_fuzzer_common", + ] +} + +# Uses Dawn specific options and varies input data +dawn_fuzzer_test("dawn_spirv_cross_msl_fast_fuzzer") { + sources = [ + "DawnSPIRVCrossGLSLFastFuzzer.cpp", + ] + deps = [ + ":dawn_spirv_cross_fuzzer_common", + ] +} + +# Varies bother the options and input data +dawn_fuzzer_test("dawn_spirv_cross_msl_full_fuzzer") { + sources = [ + "DawnSPIRVCrossGLSLFullFuzzer.cpp", + ] + deps = [ + ":dawn_spirv_cross_fuzzer_common", + ] +} + +dawn_fuzzer_test("dawn_wire_server_and_frontend_fuzzer") { + sources = [ + "DawnWireServerAndFrontendFuzzer.cpp", + ] + + deps = [ + "${dawn_top_level}:libdawn", + "${dawn_top_level}:libdawn_native", + "${dawn_top_level}:libdawn_wire", + ] + + additional_configs = [ "${dawn_top_level}:dawn_shared_library_public" ] +} diff --git a/src/fuzzers/StandaloneFuzzerMain.cpp b/src/fuzzers/StandaloneFuzzerMain.cpp new file mode 100644 index 0000000000..ba8d94b99d --- /dev/null +++ b/src/fuzzers/StandaloneFuzzerMain.cpp @@ -0,0 +1,62 @@ +// Copyright 2018 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 +#include +#include +#include + +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; + return 1; + } + + std::cout << "WARNING: this is just a best-effort reproducer for fuzzer issues in standalone " + << "Dawn builds. For the real fuzzer, please build inside Chromium." << std::endl; + + const char* filename = argv[1]; + std::cout << "Reproducing using file: " << filename << std::endl; + + std::vector data; + { + FILE* file = fopen(filename, "rb"); + if (!file) { + std::cerr << "Failed to open " << filename << std::endl; + return 1; + } + + fseek(file, 0, SEEK_END); + long tellFileSize = ftell(file); + if (tellFileSize <= 0) { + std::cerr << "Input file of incorrect size: " << filename << std::endl; + return 1; + } + fseek(file, 0, SEEK_SET); + + size_t fileSize = static_cast(tellFileSize); + data.resize(fileSize); + + size_t bytesRead = fread(data.data(), sizeof(char), fileSize, file); + fclose(file); + if (bytesRead != fileSize) { + std::cerr << "Failed to read " << filename << std::endl; + return 1; + } + } + + return LLVMFuzzerTestOneInput(reinterpret_cast(data.data()), data.size()); +}