Skip to content

Commit

Permalink
Use a build flag to turn off LITE mode
Browse files Browse the repository at this point in the history
We don't need a protoc plugin anymore. There are now generator options to
configure the optimize_for value.
protocolbuffers/protobuf#487

Change-Id: I587cc4f720705f8d8f8393555127df25ae797525
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2817620
Commit-Queue: David Benjamin <davidben@chromium.org>
Auto-Submit: David Benjamin <davidben@chromium.org>
Reviewed-by: Jonathan Metzman <metzman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#871126}
  • Loading branch information
davidben authored and Chromium LUCI CQ committed Apr 9, 2021
1 parent a13e34d commit a8fe7b3
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 202 deletions.
8 changes: 4 additions & 4 deletions testing/libfuzzer/libprotobuf-mutator.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ url_parse_proto_fuzzer.
## Write a fuzz target for code that accepts protobufs

This is almost as easy as writing a standard libFuzzer-based fuzzer. You can
look at [override_lite_runtime_plugin_test_fuzzer] for an example of a working
example of this (don't copy the line adding "//testing/libfuzzer:no_clusterfuzz"
to additional_configs). Or you can follow this walkthrough:
look at [lpm_test_fuzzer] for an example of a working example of this (don't
copy the line adding "//testing/libfuzzer:no_clusterfuzz" to
additional_configs). Or you can follow this walkthrough:

Start by creating a fuzz target. This is what the .cc file will look like:

Expand Down Expand Up @@ -365,5 +365,5 @@ fuzzer).
[this]: https://github.com/google/libprotobuf-mutator/tree/master/examples/libfuzzer/libfuzzer_example.cc
[existing proto fuzzers]: https://cs.chromium.org/search/?q=DEFINE_(BINARY_%7CTEXT_)?PROTO_FUZZER+-file:src/third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h+lang:cpp&sq=package:chromium&type=cs
[here]: https://github.com/google/libprotobuf-mutator/blob/master/README.md#utf-8-strings
[override_lite_runtime_plugin_test_fuzzer]: https://cs.chromium.org/#search&q=override_lite_runtime_plugin_test_fuzzer+file:%5Esrc/third_party/libprotobuf-mutator/BUILD.gn
[lpm_test_fuzzer]: https://cs.chromium.org/#search&q=lpm_test_fuzzer+file:%5Esrc/third_party/libprotobuf-mutator/BUILD.gn
[mojo_parse_messages_proto_fuzzer]: https://cs.chromium.org/chromium/src/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc?l=25
43 changes: 11 additions & 32 deletions third_party/libprotobuf-mutator/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -40,52 +40,31 @@ source_set("libprotobuf-mutator") {
}
}

# 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.
fuzzer_test("override_lite_runtime_plugin_test_fuzzer") {
sources = [ "protoc_plugin/test_fuzzer.cc" ]
# Test that fuzzable_proto_library works. This target contains files that are
# optimized for LITE_RUNTIME and which import other files that are also
# optimized for LITE_RUNTIME.
fuzzer_test("lpm_test_fuzzer") {
sources = [ "test_fuzzer/test_fuzzer.cc" ]
deps = [
":libprotobuf-mutator",
":override_lite_runtime_plugin_test_fuzzer_proto",
":lpm_test_fuzzer_proto",
]

# Don't actually run this on CF. It's only a test to ensure builds work.
additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
}
}

# Proto library for override_lite_runtime_plugin_test_fuzzer
fuzzable_proto_library("override_lite_runtime_plugin_test_fuzzer_proto") {
# Proto library for lpm_test_fuzzer
fuzzable_proto_library("lpm_test_fuzzer_proto") {
sources = [
"protoc_plugin/imported.proto",
"protoc_plugin/imported_publicly.proto",
"protoc_plugin/test_fuzzer_input.proto",
"test_fuzzer/imported.proto",
"test_fuzzer/imported_publicly.proto",
"test_fuzzer/test_fuzzer_input.proto",
]
}

Expand Down
18 changes: 4 additions & 14 deletions third_party/libprotobuf-mutator/fuzzable_proto_library.gni
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,25 @@
# 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
# 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("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/protobuf/proto_library.gni")

# TODO(https://crbug.com/1197634): Fold this into proto_library.
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" ]
generator_plugin_label =
"//third_party/libprotobuf-mutator:override_lite_runtime_plugin"
generator_plugin_suffix = ".pb"

# The plugin will generate cc, so don't ask for it to be done by protoc.
generate_cc = false
if (!defined(invoker.generate_python)) {
generate_python = false
}
# Override LITE_RUNTIME settings in the protobuf files.
cc_generator_options = "speed"
extra_configs = [ "//third_party/protobuf:protobuf_config" ]
}

Expand Down
124 changes: 0 additions & 124 deletions third_party/libprotobuf-mutator/protoc_plugin/protoc_plugin.cc

This file was deleted.

18 changes: 0 additions & 18 deletions third_party/libprotobuf-mutator/protoc_plugin/test_fuzzer.cc

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package lpm_protoc_plugin_test_fuzzer;
package lpm_test_fuzzer;

// Test public imported files are handled properly.
import public "imported_publicly.proto";

message Imported {
required ImportedPublicly imported_publicly = 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package lpm_protoc_plugin_test_fuzzer;
package lpm_test_fuzzer;

message ImportedPublicly {
required int32 input = 1;
Expand Down
17 changes: 17 additions & 0 deletions third_party/libprotobuf-mutator/test_fuzzer/test_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2018 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.

// Test fuzzer that when built successfully proves that fuzzable_proto_library
// is working. Building this fuzzer without using fuzzable_proto_library will
// fail because of test_fuzzer_input.proto

#include <iostream>

#include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"

#include "third_party/libprotobuf-mutator/test_fuzzer/test_fuzzer_input.pb.h"

DEFINE_PROTO_FUZZER(const lpm_test_fuzzer::TestFuzzerInput& input) {
std::cout << input.imported().imported_publicly().input() << std::endl;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Depended on by override_lite_runtime_plugin_test_fuzzer. Tests whether
// override_lite_runtime_plugin is working since without it
// builds will fail because of the optimize_for LITE_RUNTIME option this
// file has set. Also imports a file that does the same thing which complicates
// things for the plugin.
// Depended on by lpm_test_fuzzer. Tests whether fuzzable_proto_library is
// working since without it builds will fail because of the optimize_for
// LITE_RUNTIME option this file has set. Also imports a file that does the same
// thing.

syntax = "proto2";

// This line is essentially the purpose of this test fuzzer. The plugin, if
// This line is essentially the purpose of this test fuzzer. The build rule, if
// working, ignores this line. If it is not working or isn't used, then this
// build will fail.
option optimize_for = LITE_RUNTIME;

package lpm_protoc_plugin_test_fuzzer;
package lpm_test_fuzzer;
import "imported.proto";

message TestFuzzerInput {
Expand Down

0 comments on commit a8fe7b3

Please sign in to comment.