Initial ART fuzzer for DEX verification
It fuzzes the verifier by generating DEX files,
trying to open them, and verify them.
Add a small corpus to start with:
* Empty: Totally empty file (invalid DEX)
* Main: Empty main (valid DEX)
* Hello-world: Main that prints "Hello, world!"
Add a small dictionary with valid DEX headers.
Bug: 249085422
Change-Id: I9a6a555ea2462e7156669e1728815f8dcaacb23a
diff --git a/tools/fuzzer/Android.bp b/tools/fuzzer/Android.bp
new file mode 100644
index 0000000..8ade397
--- /dev/null
+++ b/tools/fuzzer/Android.bp
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "art_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["art_license"],
+}
+
+cc_fuzz {
+ name: "libart_verify_dex_fuzzer",
+ srcs: ["libart_verify_dex_fuzzer.cc"],
+ defaults: ["libart_static_defaults"],
+ // Build and run on x86 only for now.
+ host_supported: true,
+ device_supported: false,
+ corpus: ["corpus/*"],
+ dictionary: "dex.dict",
+ fuzz_config: {
+ cc: ["solanes@google.com", "art-bugs@google.com"],
+ componentid: 86431,
+ acknowledgement: [
+ "Santiago Aboy Solanes of Google",
+ ],
+ },
+}
diff --git a/tools/fuzzer/corpus/Main.dex b/tools/fuzzer/corpus/Main.dex
new file mode 100644
index 0000000..ec29035
--- /dev/null
+++ b/tools/fuzzer/corpus/Main.dex
Binary files differ
diff --git a/tools/fuzzer/corpus/empty.dex b/tools/fuzzer/corpus/empty.dex
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/fuzzer/corpus/empty.dex
diff --git a/tools/fuzzer/corpus/hello_world.dex b/tools/fuzzer/corpus/hello_world.dex
new file mode 100644
index 0000000..6e59dd7
--- /dev/null
+++ b/tools/fuzzer/corpus/hello_world.dex
Binary files differ
diff --git a/tools/fuzzer/dex.dict b/tools/fuzzer/dex.dict
new file mode 100644
index 0000000..e728414
--- /dev/null
+++ b/tools/fuzzer/dex.dict
@@ -0,0 +1,11 @@
+#
+# AFL dictionary for DEX code
+# -----------------------------
+#
+
+# Valid headers: DEX magic word + version
+header_dex_035=\x64\x65\x78\x0a\x30\x33\x35
+header_dex_037=\x64\x65\x78\x0a\x30\x33\x37
+header_dex_038=\x64\x65\x78\x0a\x30\x33\x38
+header_dex_039=\x64\x65\x78\x0a\x30\x33\x39
+header_dex_040=\x64\x65\x78\x0a\x30\x34\x30
diff --git a/tools/fuzzer/libart_verify_dex_fuzzer.cc b/tools/fuzzer/libart_verify_dex_fuzzer.cc
new file mode 100644
index 0000000..39ebe0e
--- /dev/null
+++ b/tools/fuzzer/libart_verify_dex_fuzzer.cc
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "base/mem_map.h"
+#include "dex/dex_file_loader.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Initialize environment.
+ art::MemMap::Init();
+
+ // Open and verify the DEX file. Do not verify the checksum as we only care about the DEX file
+ // contents, and know that the checksum would probably be erroneous.
+ std::string error_msg;
+ art::DexFileLoader loader(data, size, /*location=*/"");
+ std::unique_ptr<const art::DexFile> dex_file = loader.Open(
+ /*location_checksum=*/0, /*verify=*/true, /*verify_checksum=*/false, &error_msg);
+ return 0;
+}