[dart/fuzzer] Add build rule to link Dart with libFuzzer
Rationale:
First step towards integrating libFuzzer with Dart.
The initial target function is proof-of-concept.
Change-Id: I21f6ebf70fec05719423fef61fa5a9609500dc95
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96987
Commit-Queue: Aart Bik <ajcbik@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Zach Anderson <zra@google.com>
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 9ef4444..03fddb6 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -202,6 +202,12 @@
}
}
+config("dart_libfuzzer_config") {
+ defines = [ "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" ]
+ cflags = [ "-fsanitize=address,fuzzer-no-link" ]
+ ldflags = [ "-fsanitize=address,fuzzer" ]
+}
+
source_set("dart_api") {
public_configs = [ ":dart_public_config" ]
sources = [
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index f8c3141..7f04fed1 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -674,6 +674,10 @@
if (defined(invoker.extra_sources)) {
extra_sources += invoker.extra_sources
}
+ extra_ldflags = []
+ if (defined(invoker.extra_ldflags)) {
+ extra_ldflags = invoker.extra_ldflags
+ }
target_type = "executable"
if (defined(invoker.target_type)) {
target_type = invoker.target_type
@@ -722,7 +726,6 @@
"dart_embedder_api_impl.cc",
"error_exit.cc",
"error_exit.h",
- "main.cc",
"main_options.cc",
"main_options.h",
"options.cc",
@@ -743,6 +746,8 @@
ldflags = [ "-rdynamic" ]
}
+ ldflags += extra_ldflags
+
if (is_win) {
libs = [
"iphlpapi.lib",
@@ -768,10 +773,11 @@
"builtin.cc",
"dfe.cc",
"dfe.h",
- "loader.cc",
- "loader.h",
"gzip.cc",
"gzip.h",
+ "loader.cc",
+ "loader.h",
+ "main.cc",
]
if (dart_runtime_mode == "release") {
extra_sources += [ "observatory_assets_empty.cc" ]
@@ -789,11 +795,12 @@
}
extra_sources = [
"builtin.cc",
- "snapshot_empty.cc",
- "loader.cc",
- "loader.h",
"gzip.cc",
"gzip.h",
+ "loader.cc",
+ "loader.h",
+ "main.cc",
+ "snapshot_empty.cc",
]
if (dart_runtime_mode == "release") {
extra_sources += [ "observatory_assets_empty.cc" ]
@@ -808,11 +815,12 @@
}
extra_sources = [
"builtin.cc",
- "snapshot_empty.cc",
- "loader.cc",
- "loader.h",
"gzip.cc",
"gzip.h",
+ "loader.cc",
+ "loader.h",
+ "main.cc",
+ "snapshot_empty.cc",
]
if (dart_runtime_mode == "release") {
extra_sources += [ "observatory_assets_empty.cc" ]
@@ -826,12 +834,13 @@
extra_deps = [ "..:libdart_precompiled_runtime" ]
extra_sources = [
"builtin.cc",
- "snapshot_empty.cc",
- "loader.cc",
- "loader.h",
"gzip.cc",
"gzip.h",
+ "loader.cc",
+ "loader.h",
+ "main.cc",
"observatory_assets_empty.cc",
+ "snapshot_empty.cc",
]
}
@@ -1065,3 +1074,17 @@
ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
}
}
+
+dart_executable("dart_libfuzzer") {
+ extra_ldflags = [ "-fsanitize=address,fuzzer" ]
+ extra_deps = [ "..:libdart_libfuzzer" ]
+ extra_sources = [
+ "../vm/libfuzzer/dart_libfuzzer.cc",
+ "builtin.cc",
+ "dfe.cc",
+ "dfe.h",
+ ]
+ if (!exclude_kernel_service) {
+ extra_deps += [ ":dart_kernel_platform_cc" ]
+ }
+}
diff --git a/runtime/configs.gni b/runtime/configs.gni
index dacaa9c..a638887 100644
--- a/runtime/configs.gni
+++ b/runtime/configs.gni
@@ -24,6 +24,10 @@
_jit_product_config = _base_config + _product
+_base_libfuzzer_config = [ "$_dart_runtime:dart_libfuzzer_config" ]
+
+_libfuzzer_config = _base_config + _base_libfuzzer_config
+
_precompiled_runtime_config =
_base_config + [
"$_dart_runtime:dart_maybe_product_config",
@@ -94,6 +98,11 @@
configs = _nosnapshot_with_precompiler_product_fuchsia_config
snapshot = false
},
+ {
+ suffix = "_libfuzzer"
+ configs = _libfuzzer_config
+ snapshot = true
+ },
]
# This template creates a target for each of the configurations listed above.
diff --git a/runtime/vm/libfuzzer/README.md b/runtime/vm/libfuzzer/README.md
new file mode 100644
index 0000000..8ef964f
--- /dev/null
+++ b/runtime/vm/libfuzzer/README.md
@@ -0,0 +1,24 @@
+DartLibFuzzer
+=============
+
+DartLibFuzzer is a fuzzing tool built with LibFuzzer, which
+is an in-process, coverage-guided, evolutionary fuzzing engine
+(https://llvm.org/docs/LibFuzzer.html). The tool consists of a
+collection of "target functions", each of which stresses a
+particular part of the Dart runtime and compiler.
+
+How to build and run DartLibFuzzer
+==================================
+Build the dart_libfuzzer binary as follows (first either export
+DART_USE_ASAN=1 or run ./tools/gn.py --mode=debug --asan):
+
+./tools/build.py --mode debug dart_libfuzzer
+
+Then, to start a blank fuzzing session, run:
+
+dart_libfuzzer
+
+To start a fuzzing session with an initial corpus inside
+the directory CORPUS, run:
+
+dart_libfuzzer CORPUS
diff --git a/runtime/vm/libfuzzer/dart_libfuzzer.cc b/runtime/vm/libfuzzer/dart_libfuzzer.cc
new file mode 100644
index 0000000..546a620
--- /dev/null
+++ b/runtime/vm/libfuzzer/dart_libfuzzer.cc
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "platform/unicode.h"
+
+// Libfuzzer target function.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
+ // Proof-of-concept: stresses unicode methods.
+ // NOTE: already found http://dartbug.com/36235
+ dart::Utf8::Type type = dart::Utf8::kLatin1;
+ dart::Utf8::CodeUnitCount(Data, Size, &type);
+ dart::Utf8::IsValid(Data, Size);
+ int32_t dst = 0;
+ dart::Utf8::Decode(Data, Size, &dst);
+ uint16_t dst16[1024];
+ dart::Utf8::DecodeToUTF16(Data, Size, dst16, 1024);
+ int32_t dst32[1024];
+ dart::Utf8::DecodeToUTF32(Data, Size, dst32, 1024);
+ return 0;
+}