Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Carbon fuzzing 3/3: added actual fuzzer implementation and a fuzzverter utility for investigating crashing protos #1156

Merged
merged 46 commits into from
Apr 11, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
bda1633
finished fuzzer and added fuzzverter util
pk19604014 Mar 28, 2022
750874d
fixed typo
pk19604014 Mar 28, 2022
8bc26d1
renamed cmd line params
pk19604014 Mar 29, 2022
4e4dfe7
Merge branch 'trunk' of https://github.com/carbon-language/carbon-lan…
pk19604014 Mar 29, 2022
b9c07e8
fixed libproto_mutator download path
pk19604014 Mar 29, 2022
08379f6
small fixes
pk19604014 Mar 29, 2022
a2c20cc
small fixes
pk19604014 Mar 30, 2022
0e5cd09
merged
pk19604014 Mar 30, 2022
c1f0112
merged
pk19604014 Mar 30, 2022
befcfe2
small fixes
pk19604014 Mar 30, 2022
25a8f28
renamed sample corpus proto
pk19604014 Mar 30, 2022
466aab0
small fixes
pk19604014 Mar 30, 2022
7ce3607
try building on github with LIBCPP_DEBUG enabled
pk19604014 Mar 31, 2022
62e128a
temporarily marked proto fuzzer as a manual test
pk19604014 Mar 31, 2022
23797f9
code review
pk19604014 Mar 31, 2022
2c49b2e
use a dedicated proto-fuzzer feature to work around LIBCPP_DEBUG=1 cr…
pk19604014 Apr 1, 2022
f233eda
code review comments, added README.md
pk19604014 Apr 2, 2022
ddb5095
Merge branch 'trunk' of https://github.com/carbon-language/carbon-lan…
pk19604014 Apr 2, 2022
4d0e85a
minor fixes to the text
pk19604014 Apr 3, 2022
4b912de
Merge branch 'trunk' of https://github.com/carbon-language/carbon-lan…
pk19604014 Apr 6, 2022
ccb0b85
Update bazel/cc_toolchains/clang_cc_toolchain_config.bzl
pk19604014 Apr 6, 2022
a84a165
Merge branch 'trunk' of https://github.com/carbon-language/carbon-lan…
pk19604014 Apr 7, 2022
3b1aae7
use Carbon source representation for "empty Main()" instead of text f…
pk19604014 Apr 7, 2022
ce6e738
fixed typo
pk19604014 Apr 7, 2022
e976307
made FuzzerUtil produce the full carbon source (proto converted + Mai…
pk19604014 Apr 7, 2022
719d486
typo
pk19604014 Apr 7, 2022
4c0860b
Merge branch 'trunk' of https://github.com/carbon-language/carbon-lan…
pk19604014 Apr 7, 2022
a3b48c9
switched to text proto format per code review
pk19604014 Apr 7, 2022
1063754
Merge branch 'trunk' of https://github.com/carbon-language/carbon-lan…
pk19604014 Apr 7, 2022
7ffb036
Update executable_semantics/prelude.h
pk19604014 Apr 8, 2022
3b090e4
Update executable_semantics/fuzzing/README.md
pk19604014 Apr 8, 2022
06c5c5c
Update executable_semantics/fuzzing/README.md
pk19604014 Apr 8, 2022
380f874
Update executable_semantics/fuzzing/README.md
pk19604014 Apr 8, 2022
7e2bfaa
Update executable_semantics/fuzzing/README.md
pk19604014 Apr 8, 2022
c792dd6
Update executable_semantics/fuzzing/README.md
pk19604014 Apr 8, 2022
63da289
review comments
pk19604014 Apr 8, 2022
fe9669d
merged
pk19604014 Apr 8, 2022
24c4e73
removed unnecessary file mode variables
pk19604014 Apr 8, 2022
2de29d9
Update executable_semantics/fuzzing/fuzzverter.cpp
pk19604014 Apr 8, 2022
684a949
Update executable_semantics/fuzzing/README.md
pk19604014 Apr 8, 2022
febf112
Update executable_semantics/fuzzing/README.md
pk19604014 Apr 8, 2022
b9c7fee
code review comments
pk19604014 Apr 8, 2022
31d4775
Merge branch 'trunk' of https://github.com/carbon-language/carbon-lan…
pk19604014 Apr 11, 2022
f02f5f2
Update executable_semantics/syntax/BUILD
pk19604014 Apr 11, 2022
b6dedc2
Merge branch 'executable_semantics_fuzzer' of https://github.com/pk19…
pk19604014 Apr 11, 2022
35adb05
buildifier
pk19604014 Apr 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,41 @@ rules_proto_dependencies()

rules_proto_toolchains()

###############################################################################
# libprotobuf_mutator - for structured fuzzer testing.
###############################################################################

# libprotobuf_mutator uses cmake and doesn't provide a bazel BUILD file.
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved
MUTATOR_BUILD = """
load("@rules_cc//cc:defs.bzl", "cc_library")
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved

cc_library(
name = "libprotobuf_mutator",
srcs = glob(
[
"src/**/*.cc",
"src/**/*.h",
"port/protobuf.h",
],
exclude = ["**/*_test.cc"],
),
hdrs = ["src/libfuzzer/libfuzzer_macro.h"],
include_prefix = "libprotobuf_mutator",
visibility = ["//visibility:public"],
deps = ["@com_google_protobuf//:protobuf"],
)
"""

libprotobuf_mutator_version = "1.0"

http_archive(
name = "com_google_libprotobuf_mutator",
build_file_content = MUTATOR_BUILD,
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved
sha256 = "792f250fb546bde8590e72d64311ea00a70c175fd77df6bb5e02328fa15fe28e",
strip_prefix = "libprotobuf-mutator-%s" % libprotobuf_mutator_version,
urls = ["https://github.com/google/libprotobuf-mutator/archive/v%s.tar.gz" % libprotobuf_mutator_version],
)

###############################################################################
# Example conversion repositories
###############################################################################
Expand Down
5 changes: 4 additions & 1 deletion bazel/cc_toolchains/clang_cc_toolchain_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,10 @@ def _impl(ctx):
"-D_LIBCPP_DEBUG=1",
])],
with_features = [
with_feature_set(not_features = ["opt"]),
# _LIBCPP_DEBUG=1 causes protobuf code to crash under asan
# with the following error:
# 'Attempted to dereference a non-dereferenceable iterator'.
with_feature_set(not_features = ["opt", "asan"]),
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved
],
),
],
Expand Down
16 changes: 15 additions & 1 deletion executable_semantics/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,25 @@ filegroup(
srcs = ["data/prelude.carbon"],
)

cc_library(
name = "prelude",
srcs = ["prelude.cpp"],
hdrs = ["prelude.h"],
data = [":standard_libraries"],
deps = [
"//common:error",
"//executable_semantics/ast:declaration",
"//executable_semantics/common:arena",
"//executable_semantics/common:nonnull",
"//executable_semantics/syntax",
],
)
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved

cc_binary(
name = "executable_semantics",
srcs = ["main.cpp"],
data = [":standard_libraries"],
deps = [
":prelude",
"//common:error",
"//executable_semantics/common:arena",
"//executable_semantics/common:nonnull",
Expand Down
50 changes: 50 additions & 0 deletions executable_semantics/fuzzing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# Exceptions. See /LICENSE for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

load("//bazel/fuzzing:rules.bzl", "cc_fuzz_test")

cc_library(
name = "ast_to_proto_lib",
srcs = ["ast_to_proto.cpp"],
Expand All @@ -15,6 +17,19 @@ cc_library(
],
)

cc_library(
name = "fuzzer_util",
srcs = ["fuzzer_util.cpp"],
hdrs = ["fuzzer_util.h"],
deps = [
"//common:check",
"//common/fuzzing:carbon_cc_proto",
"//executable_semantics/ast",
"@com_google_protobuf//:protobuf_headers",
"@llvm-project//llvm:Support",
],
)

cc_test(
name = "ast_to_proto_test",
srcs = ["ast_to_proto_test.cpp"],
Expand All @@ -36,6 +51,23 @@ cc_test(
],
)

cc_binary(
name = "fuzzverter",
srcs = ["fuzzverter.cpp"],
deps = [
":ast_to_proto_lib",
":fuzzer_util",
"//common:error",
"//common/fuzzing:carbon_cc_proto",
"//common/fuzzing:proto_to_carbon_lib",
"//executable_semantics/common:error",
"//executable_semantics/common:nonnull",
"//executable_semantics/syntax",
"@com_google_protobuf//:protobuf_headers",
"@llvm-project//llvm:Support",
],
)

cc_test(
name = "proto_to_carbon_test",
srcs = ["proto_to_carbon_test.cpp"],
Expand All @@ -57,3 +89,21 @@ cc_test(
"@llvm-project//llvm:Support",
],
)

cc_fuzz_test(
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved
name = "executable_semantics_fuzzer",
size = "small",
srcs = ["executable_semantics_fuzzer.cpp"],
corpus = glob(["fuzzer_corpus/**"]),
deps = [
":fuzzer_util",
"//common/fuzzing:carbon_cc_proto",
"//common/fuzzing:proto_to_carbon_lib",
"//executable_semantics:prelude",
"//executable_semantics/interpreter:exec_program",
"//executable_semantics/syntax",
"@com_google_libprotobuf_mutator//:libprotobuf_mutator",
"@com_google_protobuf//:protobuf_headers",
"@llvm-project//llvm:Support",
],
)
46 changes: 46 additions & 0 deletions executable_semantics/fuzzing/executable_semantics_fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <google/protobuf/text_format.h>
#include <libprotobuf_mutator/src/libfuzzer/libfuzzer_macro.h>

#include "common/fuzzing/carbon.pb.h"
#include "common/fuzzing/proto_to_carbon.h"
#include "executable_semantics/fuzzing/fuzzer_util.h"
#include "executable_semantics/interpreter/exec_program.h"
#include "executable_semantics/prelude.h"
#include "executable_semantics/syntax/parse.h"
#include "llvm/Support/raw_ostream.h"

namespace Carbon {

// Parses and executes a fuzzer-generated program.
// Takes `compilation_unit` by value to allow modifications like adding
// `Main()`.
void ParseAndExecute(Fuzzing::CompilationUnit compilation_unit) {
MaybeAddMain(compilation_unit);
const std::string source = ProtoToCarbon(compilation_unit);

Arena arena;
ErrorOr<AST> ast = ParseFromString(&arena, "Fuzzer.carbon", source,
/*trace=*/false);
if (!ast.ok()) {
llvm::errs() << "Parsing failed: " << ast.error().message() << "\n";
return;
}
AddPrelude("executable_semantics/data/prelude.carbon", &arena,
&ast->declarations);
const ErrorOr<int> result = ExecProgram(&arena, *ast, /*trace=*/false);
if (!result.ok()) {
llvm::errs() << "Execution failed: " << result.error().message() << "\n";
return;
}
llvm::outs() << "Executed OK: " << *result;
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved
}

} // namespace Carbon

DEFINE_BINARY_PROTO_FUZZER(const Carbon::Fuzzing::Carbon& input) {
Carbon::ParseAndExecute(input.compilation_unit());
}
Empty file.
48 changes: 48 additions & 0 deletions executable_semantics/fuzzing/fuzzer_util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "executable_semantics/fuzzing/fuzzer_util.h"

#include <google/protobuf/text_format.h>

#include "common/check.h"

namespace Carbon {

// Appended to fuzzer-generated AST proto when the proto is missing
// `Main()` definition, to prevent early error return in semantic analysis.
static constexpr char EmptyMainDeclaration[] = R"pb(
function {
name: "Main"
param_pattern {}
return_term {
kind: Expression
type { int_type_literal {} }
}
body {
statements {
return_statement { expression { int_literal { value: 0 } } }
}
}
}
)pb";

auto MaybeAddMain(Fuzzing::CompilationUnit& compilation_unit) -> void {
const bool has_main = std::any_of(
compilation_unit.declarations().begin(),
compilation_unit.declarations().end(),
[](const Fuzzing::Declaration& decl) {
return decl.kind_case() == Fuzzing::Declaration::kFunction &&
decl.function().name() == "Main";
});
if (!has_main) {
Fuzzing::Declaration main_decl;
CHECK(google::protobuf::TextFormat::ParseFromString(EmptyMainDeclaration,
&main_decl))
<< "Failed to parse " << EmptyMainDeclaration;
*compilation_unit.add_declarations() = main_decl;
}
}

} // namespace Carbon
17 changes: 17 additions & 0 deletions executable_semantics/fuzzing/fuzzer_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef THIRD_PARTY_CARBON_LANG_EXECUTABLE_SEMANTICS_FUZZING_FUZZER_UTIL_H_
pk19604014 marked this conversation as resolved.
Show resolved Hide resolved
#define THIRD_PARTY_CARBON_LANG_EXECUTABLE_SEMANTICS_FUZZING_FUZZER_UTIL_H_

#include "common/fuzzing/carbon.pb.h"

namespace Carbon {

// Adds an empty `Main()` declaration if `compilation_unit` does not have one.
auto MaybeAddMain(Fuzzing::CompilationUnit& compilation_unit) -> void;

} // namespace Carbon

#endif // THIRD_PARTY_CARBON_LANG_EXECUTABLE_SEMANTICS_FUZZING_FUZZER_UTIL_H_
Loading