diff --git a/.bazelrc b/.bazelrc index bb94580..34d51af 100644 --- a/.bazelrc +++ b/.bazelrc @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Force the use of Clang for all builds. +# Set clang as the default compiler for most configurations. build --repo_env=CC=clang # Needed for abseil-cpp until https://github.com/bazelbuild/bazel/pull/19794 is released. @@ -74,6 +74,13 @@ build:ubsan-honggfuzz --//fuzzing:cc_engine=//fuzzing/engines:honggfuzz build:ubsan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=honggfuzz build:ubsan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=ubsan +# Honggfuzz + ASAN (GCC) +build:asan-honggfuzz-gcc --//fuzzing:cc_engine=//fuzzing/engines:honggfuzz +build:asan-honggfuzz-gcc --@rules_fuzzing//fuzzing:cc_engine_instrumentation=honggfuzz +build:asan-honggfuzz-gcc --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan +build:asan-honggfuzz-gcc --repo_env=CC=gcc +build:asan-honggfuzz-gcc --@rules_fuzzing//fuzzing:compiler_type=gcc + # Replay + ASAN build:asan-replay --//fuzzing:cc_engine=//fuzzing/engines:replay build:asan-replay --@rules_fuzzing//fuzzing:cc_engine_instrumentation=none diff --git a/README.md b/README.md index 0aa2822..44f6fca 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,10 @@ This section will walk you through the steps to set up fuzzing in your Bazel pro The fuzzing rules have been tested on Bazel 4.0.0 or later. Check your Bazel version by running `bazel --version`. -C++ fuzzing requires a Clang compiler. The libFuzzer engine requires at least Clang 6.0. In addition, the Honggfuzz engine requires the `libunwind-dev` and `libblocksruntime-dev` packages: +The libFuzzer engine requires at least Clang 6.0. Honggfuzz works with both clang and gcc (8 or later) and requires the `libunwind-dev` and `libblocksruntime-dev` packages: ```sh -$ sudo apt-get install clang libunwind-dev libblocksruntime-dev +$ sudo apt-get install libunwind-dev libblocksruntime-dev ``` Java fuzzing requires Clang and the LLD linker: diff --git a/fuzzing/BUILD b/fuzzing/BUILD index fbf654a..67d76c8 100644 --- a/fuzzing/BUILD +++ b/fuzzing/BUILD @@ -73,6 +73,22 @@ bool_flag( visibility = ["//visibility:public"], ) +string_flag( + name = "compiler_type", + build_setting_default = "clang", + values = [ + "clang", + "gcc", + ], + visibility = ["//visibility:public"], +) + +config_setting( + name = "is_gcc", + flag_values = {":compiler_type": "gcc"}, + visibility = ["//visibility:public"], +) + exports_files([ "cc_defs.bzl", "java_defs.bzl", diff --git a/fuzzing/instrum_opts.bzl b/fuzzing/instrum_opts.bzl index a6eadbe..19272e9 100644 --- a/fuzzing/instrum_opts.bzl +++ b/fuzzing/instrum_opts.bzl @@ -29,21 +29,35 @@ load( "oss_fuzz_opts", ) -# Fuzz test binary instrumentation configurations. +# Fuzz test binary instrumentation configurations by compiler type. instrum_configs = { - "none": instrum_opts.make(), - "libfuzzer": instrum_defaults.libfuzzer, - "jazzer": instrum_defaults.jazzer, - "honggfuzz": instrum_defaults.honggfuzz, - "oss-fuzz": oss_fuzz_opts, + "clang": { + "none": instrum_opts.make(), + "libfuzzer": instrum_defaults.libfuzzer, + "jazzer": instrum_defaults.jazzer, + "honggfuzz": instrum_defaults.honggfuzz_clang, + "oss-fuzz": oss_fuzz_opts, + }, + "gcc": { + "none": instrum_opts.make(), + "honggfuzz": instrum_defaults.honggfuzz_gcc, + }, } -# Sanitizer configurations. +# Sanitizer configurations by compiler type. sanitizer_configs = { - "none": instrum_opts.make(), - "asan": instrum_defaults.asan, - "msan": instrum_defaults.msan, - "msan-origin-tracking": instrum_defaults.msan_origin_tracking, - "ubsan": instrum_defaults.ubsan, - "asan-ubsan": instrum_opts.merge(instrum_defaults.asan, instrum_defaults.ubsan), + "clang": { + "none": instrum_opts.make(), + "asan": instrum_defaults.asan, + "msan": instrum_defaults.msan, + "msan-origin-tracking": instrum_defaults.msan_origin_tracking, + "ubsan": instrum_defaults.ubsan_clang, + "asan-ubsan": instrum_opts.merge(instrum_defaults.asan, instrum_defaults.ubsan_clang), + }, + "gcc": { + "none": instrum_opts.make(), + "asan": instrum_defaults.asan, + "ubsan": instrum_defaults.ubsan_gcc, + "asan-ubsan": instrum_opts.merge(instrum_defaults.asan, instrum_defaults.ubsan_gcc), + }, } diff --git a/fuzzing/private/binary.bzl b/fuzzing/private/binary.bzl index 8ff9723..2694bb1 100644 --- a/fuzzing/private/binary.bzl +++ b/fuzzing/private/binary.bzl @@ -54,22 +54,23 @@ def _fuzzing_binary_transition_impl(settings, _attr): cxxopts = settings["//command_line_option:cxxopt"], linkopts = settings["//command_line_option:linkopt"], ) + compiler_type = settings["@rules_fuzzing//fuzzing:compiler_type"] is_fuzzing_build_mode = settings["@rules_fuzzing//fuzzing:cc_fuzzing_build_mode"] if is_fuzzing_build_mode: opts = instrum_opts.merge(opts, instrum_defaults.fuzzing_build) instrum_config = settings["@rules_fuzzing//fuzzing:cc_engine_instrumentation"] - if instrum_config in instrum_configs: - opts = instrum_opts.merge(opts, instrum_configs[instrum_config]) + if instrum_config in instrum_configs[compiler_type]: + opts = instrum_opts.merge(opts, instrum_configs[compiler_type][instrum_config]) else: - fail("unsupported engine instrumentation '%s'" % instrum_config) + fail("unsupported engine instrumentation '%s' for compiler '%s'" % (instrum_config, compiler_type)) sanitizer_config = settings["@rules_fuzzing//fuzzing:cc_engine_sanitizer"] - if sanitizer_config in sanitizer_configs: - opts = instrum_opts.merge(opts, sanitizer_configs[sanitizer_config]) + if sanitizer_config in sanitizer_configs[compiler_type]: + opts = instrum_opts.merge(opts, sanitizer_configs[compiler_type][sanitizer_config]) else: - fail("unsupported sanitizer '%s'" % sanitizer_config) + fail("unsupported sanitizer '%s' for compiler '%s'" % (sanitizer_config, compiler_type)) return { "//command_line_option:copt": opts.copts, @@ -87,6 +88,7 @@ fuzzing_binary_transition = transition( "@rules_fuzzing//fuzzing:cc_engine_instrumentation", "@rules_fuzzing//fuzzing:cc_engine_sanitizer", "@rules_fuzzing//fuzzing:cc_fuzzing_build_mode", + "@rules_fuzzing//fuzzing:compiler_type", "//command_line_option:copt", "//command_line_option:conlyopt", "//command_line_option:cxxopt", diff --git a/fuzzing/private/instrum_opts.bzl b/fuzzing/private/instrum_opts.bzl index 60cea93..1c723bb 100644 --- a/fuzzing/private/instrum_opts.bzl +++ b/fuzzing/private/instrum_opts.bzl @@ -91,7 +91,7 @@ instrum_defaults = struct( ), # Reflects the set of options at # https://github.com/google/honggfuzz/blob/master/hfuzz_cc/hfuzz-cc.c - honggfuzz = _make_opts( + honggfuzz_clang = _make_opts( copts = [ "-mllvm", "-inline-threshold=2000", @@ -105,6 +105,16 @@ instrum_defaults = struct( "-fno-sanitize=fuzzer", ], ), + honggfuzz_gcc = _make_opts( + copts = [ + "-finline-limit=1000", + "-fsanitize-coverage=trace-pc,trace-cmp", + "-fno-builtin", + "-fno-omit-frame-pointer", + "-D__NO_STRING_INLINES", + ], + linkopts = [], + ), asan = _make_opts( copts = ["-fsanitize=address"], linkopts = ["-fsanitize=address"], @@ -120,7 +130,7 @@ instrum_defaults = struct( ], linkopts = ["-fsanitize=memory"], ), - ubsan = _make_opts( + ubsan_clang = _make_opts( copts = [ "-fsanitize=undefined", ], @@ -133,4 +143,12 @@ instrum_defaults = struct( "-fsanitize-link-c++-runtime", ], ), + ubsan_gcc = _make_opts( + copts = [ + "-fsanitize=undefined", + ], + linkopts = [ + "-fsanitize=undefined", + ], + ), ) diff --git a/fuzzing/repositories.bzl b/fuzzing/repositories.bzl index 22e2864..40e2a95 100644 --- a/fuzzing/repositories.bzl +++ b/fuzzing/repositories.bzl @@ -71,9 +71,9 @@ def rules_fuzzing_dependencies(oss_fuzz = True, honggfuzz = True, jazzer = True) http_archive, name = "honggfuzz", build_file = "@rules_fuzzing//:honggfuzz.BUILD", - sha256 = "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e", - url = "https://github.com/google/honggfuzz/archive/2.5.zip", - strip_prefix = "honggfuzz-2.5", + integrity = "sha256-d+DpDrzBMqmSNCuz0+/Vi3jTUiIFNnulWGAeBJaaHJM=", + url = "https://github.com/google/honggfuzz/archive/4cfa62f4fdb56e3027c1cb3aecf04812e786f0fd.zip", + strip_prefix = "honggfuzz-4cfa62f4fdb56e3027c1cb3aecf04812e786f0fd", ) if jazzer: diff --git a/honggfuzz.BUILD b/honggfuzz.BUILD index 29d9fca..292e481 100644 --- a/honggfuzz.BUILD +++ b/honggfuzz.BUILD @@ -34,20 +34,31 @@ COMMON_COPTS = [ "-Wall", "-Wextra", "-Werror", - "-Wno-override-init", - "-Wno-initializer-overrides", - "-Wno-gnu-empty-initializer", - "-Wno-format-pedantic", - "-Wno-gnu-statement-expression", - "-mllvm", - "-inline-threshold=2000", - "-fblocks", - - # Do not instrument Honggfuzz itself, in order to avoid recursive - # instrumentation calls that would crash the fuzz test binary. - "-fsanitize-coverage=0", - "-fno-sanitize=all", -] +] + select({ + "@rules_fuzzing//fuzzing:is_gcc": [ + "-Wno-override-init", + "-Wno-format-truncation", + # Do not instrument Honggfuzz itself, in order to avoid recursive + # instrumentation calls that would crash the fuzz test binary. + "-fno-sanitize-coverage=trace-pc,trace-cmp", + "-fno-sanitize=all", + ], + # Default to clang compiler flags + "//conditions:default": [ + "-mllvm", + "-inline-threshold=2000", + "-fblocks", + "-Wno-override-init", + "-Wno-initializer-overrides", + "-Wno-gnu-empty-initializer", + "-Wno-format-pedantic", + "-Wno-gnu-statement-expression", + # Do not instrument Honggfuzz itself, in order to avoid recursive + # instrumentation calls that would crash the fuzz test binary. + "-fsanitize-coverage=0", + "-fno-sanitize=all", + ], +}) LIBRARY_COPTS = [ "-fno-stack-protector", @@ -113,6 +124,10 @@ SYMBOL_WRAP_LINKOPTS = select({ "-Wl,--wrap=Curl_safe_strcasecompare", "-Wl,--wrap=Curl_strncasecompare", "-Wl,--wrap=curl_strnequal", + # SQLite3 + "-Wl,--wrap=sqlite3_stricmp", + "-Wl,--wrap=sqlite3_strnicmp", + "-Wl,--wrap=sqlite3StrICmp", ], })