aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--DEPS6
-rw-r--r--build/config/BUILD.gn3
-rw-r--r--build/config/BUILDCONFIG.gn3
-rw-r--r--cast/common/channel/proto/BUILD.gn3
-rw-r--r--testing/libfuzzer/fuzzer_test.gni17
-rw-r--r--third_party/libprotobuf-mutator/BUILD.gn87
-rw-r--r--third_party/libprotobuf-mutator/fuzzable_proto_library.gni62
-rw-r--r--third_party/protobuf/BUILD.gn1
8 files changed, 166 insertions, 16 deletions
diff --git a/DEPS b/DEPS
index 82eef6ca..5e7cf6cc 100644
--- a/DEPS
+++ b/DEPS
@@ -51,6 +51,12 @@ deps = {
'condition': 'not build_with_chromium',
},
+ 'third_party/libprotobuf-mutator/src': {
+ 'url': Var('chromium_git') +
+ '/external/github.com/google/libprotobuf-mutator.git' + '@' '439e81f8f4847ec6e2bf11b3aa634a5d8485633d',
+ 'condition': 'not build_with_chromium',
+ },
+
'third_party/zlib/src': {
'url': Var('github') +
'/madler/zlib.git' +
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index a153e5b1..a68031e8 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -16,9 +16,6 @@ declare_args() {
# Enable thread sanitizer.
is_tsan = false
- # Must be enabled for fuzzing targets.
- use_libfuzzer = false
-
# Enables clang's source-based coverage (requires is_clang=true).
# NOTE: This will slow down the build and increase binary size
# significantly. For more details, see:
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 4e69143f..0fa96935 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -75,6 +75,9 @@ declare_args() {
# further explanation, see
# https://gn.googlesource.com/gn/+/refs/heads/master/docs/reference.md#toolchain-overview
host_toolchain = ""
+
+ # Must be enabled for fuzzing targets.
+ use_libfuzzer = false
}
declare_args() {
diff --git a/cast/common/channel/proto/BUILD.gn b/cast/common/channel/proto/BUILD.gn
index 13ee38af..152cb450 100644
--- a/cast/common/channel/proto/BUILD.gn
+++ b/cast/common/channel/proto/BUILD.gn
@@ -3,9 +3,10 @@
# found in the LICENSE file.
import("//build_overrides/build.gni")
+import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
import("//third_party/protobuf/proto_library.gni")
-proto_library("channel_proto") {
+fuzzable_proto_library("channel_proto") {
sources = [
"authority_keys.proto",
"cast_channel.proto",
diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni
index 4de38ac4..cbd33178 100644
--- a/testing/libfuzzer/fuzzer_test.gni
+++ b/testing/libfuzzer/fuzzer_test.gni
@@ -75,9 +75,7 @@ template("openscreen_fuzzer_test") {
}
}
- outputs = [
- out,
- ]
+ outputs = [ out ]
deps = [ "//testing/libfuzzer:seed_corpus" ] + seed_corpus_deps
}
@@ -92,12 +90,8 @@ template("openscreen_fuzzer_test") {
if (defined(invoker.dict)) {
# Copy dictionary to output.
copy(target_name + "_dict_copy") {
- sources = [
- invoker.dict,
- ]
- outputs = [
- "$root_build_dir/" + target_name + ".dict",
- ]
+ sources = [ invoker.dict ]
+ outputs = [ "$root_build_dir/" + target_name + ".dict" ]
}
test_deps += [ ":" + target_name + "_dict_copy" ]
}
@@ -144,14 +138,13 @@ template("openscreen_fuzzer_test") {
args += invoker.environment_variables
}
- outputs = [
- "$root_build_dir/$config_file_name",
- ]
+ outputs = [ "$root_build_dir/$config_file_name" ]
}
test_deps += [ ":" + config_file_name ]
}
executable(target_name) {
+ testonly = true
forward_variables_from(invoker,
[
"cflags",
diff --git a/third_party/libprotobuf-mutator/BUILD.gn b/third_party/libprotobuf-mutator/BUILD.gn
new file mode 100644
index 00000000..cc3eeaeb
--- /dev/null
+++ b/third_party/libprotobuf-mutator/BUILD.gn
@@ -0,0 +1,87 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build_overrides/build.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
+import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
+
+config("include_config") {
+ include_dirs = [ "src/" ]
+}
+
+source_set("libprotobuf-mutator") {
+ testonly = true
+
+ configs += [ ":include_config" ]
+
+ public_configs = [ ":include_config" ]
+ sources = [
+ "src/src/binary_format.cc",
+ "src/src/libfuzzer/libfuzzer_macro.cc",
+ "src/src/libfuzzer/libfuzzer_mutator.cc",
+ "src/src/mutator.cc",
+ "src/src/text_format.cc",
+ "src/src/utf8_fix.cc",
+ ]
+
+ # Allow users of LPM to use protobuf reflection and other features from
+ # protobuf_full.
+ public_deps = [ "//third_party/protobuf:protobuf_full" ]
+}
+
+# This protoc plugin, like the compiler, should only be built for the host
+# architecture.
+if (current_toolchain == host_toolchain) {
+ # This plugin will be needed to fuzz most protobuf code in Chromium. That's
+ # because production protobuf code must contain the line:
+ # "option optimize_for = LITE_RUNTIME", which instructs the proto compiler not
+ # to compile the proto using the full protobuf runtime. This allows Chromium
+ # not to depend on the full protobuf library, but prevents
+ # libprotobuf-mutator from fuzzing because the lite runtime lacks needed
+ # features (such as reflection). The plugin simply compiles a proto library
+ # as normal but ensures that is compiled with the full protobuf runtime.
+ executable("override_lite_runtime_plugin") {
+ sources = [ "protoc_plugin/protoc_plugin.cc" ]
+ deps = [ "//third_party/protobuf:protoc_lib" ]
+ public_configs = [ "//third_party/protobuf:protobuf_config" ]
+ }
+ # To use the plugin in a proto_library you want to fuzz, change the build
+ # target to fuzzable_proto_library (defined in
+ # //third_party/libprotobuf-mutator/fuzzable_proto_library.gni)
+}
+
+# The CQ will try building this target without "use_libfuzzer" if it is defined.
+# That will cause the build to fail, so don't define it when "use_libfuzzer" is
+# is false.
+if (use_libfuzzer) {
+ # Test that override_lite_runtime_plugin is working when built. This target
+ # contains files that are optimized for LITE_RUNTIME and which import other
+ # files that are also optimized for LITE_RUNTIME.
+ openscreen_fuzzer_test("override_lite_runtime_plugin_test_fuzzer") {
+ sources = [ "protoc_plugin/test_fuzzer.cc" ]
+ deps = [
+ ":libprotobuf-mutator",
+ ":override_lite_runtime_plugin_test_fuzzer_proto",
+ ]
+ }
+}
+
+# Proto library for override_lite_runtime_plugin_test_fuzzer
+fuzzable_proto_library("override_lite_runtime_plugin_test_fuzzer_proto") {
+ sources = [
+ "protoc_plugin/imported.proto",
+ "protoc_plugin/imported_publicly.proto",
+ "protoc_plugin/test_fuzzer_input.proto",
+ ]
+}
+
+# Avoid CQ complaints on platforms we don't care about (ie: iOS).
+# Also prevent people from using this to include protobuf_full into a production
+# build of Chrome.
+if (use_libfuzzer) {
+ # Component that can provide protobuf_full to non-testonly targets
+ static_library("protobuf_full") {
+ public_deps = [ "//third_party/protobuf:protobuf_full" ]
+ }
+}
diff --git a/third_party/libprotobuf-mutator/fuzzable_proto_library.gni b/third_party/libprotobuf-mutator/fuzzable_proto_library.gni
new file mode 100644
index 00000000..fee136c6
--- /dev/null
+++ b/third_party/libprotobuf-mutator/fuzzable_proto_library.gni
@@ -0,0 +1,62 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# A fuzzable_proto_library is a proto_library that is the same as any other in
+# non-fuzzer builds (ie: use_libfuzzer=false). However, in fuzzer builds, the
+# proto_library is built with the full protobuf runtime and any "optimize_for =
+# LITE_RUNTIME" options are ignored. This is done because libprotobuf-mutator
+# needs the full protobuf runtime, but proto_libraries shipped in chrome must
+# use the optimize for LITE_RUNTIME option which is incompatible with the full
+# protobuf runtime. tl;dr: A fuzzable_proto_library is a proto_library that can
+# be fuzzed with libprotobuf-mutator and shipped in Chrome.
+
+import("//build_overrides/build.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
+import("//third_party/protobuf/proto_library.gni")
+
+template("fuzzable_proto_library") {
+ # Only make the proto library fuzzable if we are doing a build that we can
+ # use LPM on (i.e. libFuzzer not on Chrome OS).
+ if (use_libfuzzer && current_toolchain != "//build/toolchain/cros:target") {
+ proto_library("proto_library_" + target_name) {
+ forward_variables_from(invoker, "*")
+ assert(current_toolchain == host_toolchain)
+ if (!defined(proto_deps)) {
+ proto_deps = []
+ }
+ proto_deps +=
+ [ "//third_party/libprotobuf-mutator:override_lite_runtime_plugin" ]
+
+ extra_configs = [ "//third_party/protobuf:protobuf_config" ]
+ }
+
+ # Inspired by proto_library.gni's handling of
+ # component_build_force_source_set.
+ if (defined(component_build_force_source_set) &&
+ component_build_force_source_set && is_component_build) {
+ link_target_type = "source_set"
+ } else {
+ link_target_type = "static_library"
+ }
+
+ # By making target a static_library or source_set, we can add protobuf_full
+ # to public_deps.
+ target(link_target_type, target_name) {
+ if (defined(invoker.testonly)) {
+ testonly = invoker.testonly
+ }
+ sources = [ "//third_party/libprotobuf-mutator/dummy.cc" ]
+ public_deps = [
+ ":proto_library_" + target_name,
+ "//third_party/libprotobuf-mutator:protobuf_full",
+ ]
+ }
+ } else {
+ # fuzzable_proto_library should behave like a proto_library when
+ # !use_libfuzzer.
+ proto_library(target_name) {
+ forward_variables_from(invoker, "*")
+ }
+ }
+}
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index aa898d12..11516480 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -198,6 +198,7 @@ static_library("protobuf_full") {
visibility = [
":protoc_lib",
"../chromium_quic/src/third_party:quic_trace",
+ "//third_party/libprotobuf-mutator:*",
]
}