aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorckitagawa <ckitagawa@chromium.org>2021-09-07 21:12:21 +0000
committerCopybara-Service <copybara-worker@google.com>2021-09-07 14:22:35 -0700
commit1269b5c6a8a1275b7dfdb7ec349f1990bc7c5d77 (patch)
tree5e5fb506f823182f1e6a11042a1119ec75925392
parent737d35c6383995ae4d474cd975aebf92aaf73393 (diff)
downloadzucchini-1269b5c6a8a1275b7dfdb7ec349f1990bc7c5d77.tar.gz
[Zucchini] DEX Version 39 Support
DEX Version 39 added: * const-method-handle containing a method_handle@BBBB reference * const-method-type containing a proto@BBBB reference This CL * Updates CodeToProtoId for const-method-type * Adds CodeToMethodHandle and WriteMethodHandle Fuzzed about 500k iterations locally and uploaded new samples to the clusterfuzz bucket. 97% coverage. Manually tested on hand-written dex files using smali as well as the dexdump test corpus. Bug: 1231885 Change-Id: Id8ab09ac8d3331902c5e6f92ac39ebd26d36e79b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3060660 Commit-Queue: Calder Kitagawa <ckitagawa@chromium.org> Reviewed-by: Samuel Huang <huangs@chromium.org> Reviewed-by: Etienne Pierre-Doray <etiennep@chromium.org> Cr-Commit-Position: refs/heads/main@{#918948} NOKEYCHECK=True GitOrigin-RevId: d08c50abf7b49f3a5b97a03d5bb79bce9fdb7fad
-rw-r--r--disassembler_dex.cc54
-rw-r--r--disassembler_dex.h8
-rw-r--r--testdata/const-method-type-min.smali16
-rw-r--r--type_dex.h4
4 files changed, 71 insertions, 11 deletions
diff --git a/disassembler_dex.cc b/disassembler_dex.cc
index 74c5e69..8ea0314 100644
--- a/disassembler_dex.cc
+++ b/disassembler_dex.cc
@@ -844,10 +844,11 @@ bool ReadDexHeader(ConstBufferView image, ReadDexHeaderResults* opt_results) {
dex_version = dex_version * 10 + (header->magic[i] - '0');
}
- // Only support DEX versions 35, 37, and 38.
- // TODO(ckitagawa): Handle version 39.
- if (dex_version != 35 && dex_version != 37 && dex_version != 38)
+ // Only support DEX versions 35, 37, 38, and 39
+ if (dex_version != 35 && dex_version != 37 && dex_version != 38 &&
+ dex_version != 39) {
return false;
+ }
if (header->file_size > image.size() ||
header->file_size < sizeof(dex::HeaderItem) ||
@@ -960,6 +961,9 @@ std::vector<ReferenceGroup> DisassemblerDex::MakeReferenceGroups() const {
{{2, TypeTag(kCodeToCallSiteId), PoolTag(kCallSiteId)},
&DisassemblerDex::MakeReadCodeToCallSiteId16,
&DisassemblerDex::MakeWriteCallSiteId16},
+ {{2, TypeTag(kCodeToMethodHandle), PoolTag(kMethodHandle)},
+ &DisassemblerDex::MakeReadCodeToMethodHandle16,
+ &DisassemblerDex::MakeWriteMethodHandle16},
{{4, TypeTag(kProtoIdToParametersTypeList), PoolTag(kTypeList)},
&DisassemblerDex::MakeReadProtoIdToParametersTypeList,
&DisassemblerDex::MakeWriteAbs32},
@@ -1424,12 +1428,17 @@ std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToProtoId16(
offset_t hi) {
auto filter = base::BindRepeating(
[](const InstructionParser::Value& value) -> offset_t {
- if (value.instr->format == dex::FormatId::c &&
- (value.instr->opcode == 0xFA || // invoke-polymorphic
- value.instr->opcode == 0xFB)) { // invoke-polymorphic/range
- // HHHH from e.g, invoke-polymorphic {vC, vD, vE, vF, vG},
- // meth@BBBB, proto@HHHH
- return value.instr_offset + 6;
+ if (value.instr->format == dex::FormatId::c) {
+ if (value.instr->opcode == 0xFA || // invoke-polymorphic
+ value.instr->opcode == 0xFB) { // invoke-polymorphic/range
+ // HHHH from e.g, invoke-polymorphic {vC, vD, vE, vF, vG},
+ // meth@BBBB, proto@HHHH
+ return value.instr_offset + 6;
+ }
+ if (value.instr->opcode == 0xFF) { // const-method-type
+ // BBBB from e.g., const-method-type vAA, proto@BBBB
+ return value.instr_offset + 2;
+ }
}
return kInvalidOffset;
});
@@ -1460,6 +1469,25 @@ std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToCallSiteId16(
image_, lo, hi, code_item_offsets_, std::move(filter), std::move(mapper));
}
+std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToMethodHandle16(
+ offset_t lo,
+ offset_t hi) {
+ auto filter = base::BindRepeating(
+ [](const InstructionParser::Value& value) -> offset_t {
+ if (value.instr->format == dex::FormatId::c &&
+ value.instr->opcode == 0xFE) { // const-method-handle
+ // BBBB from e.g, const-method-handle vAA, method_handle@BBBB
+ return value.instr_offset + 2;
+ }
+ return kInvalidOffset;
+ });
+ auto mapper = base::BindRepeating(ReadTargetIndex<uint16_t>, image_,
+ method_handle_map_item_,
+ sizeof(dex::MethodHandleItem));
+ return std::make_unique<InstructionReferenceReader>(
+ image_, lo, hi, code_item_offsets_, std::move(filter), std::move(mapper));
+}
+
std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToFieldId16(
offset_t lo,
offset_t hi) {
@@ -1666,6 +1694,14 @@ std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteCallSiteId16(
return std::make_unique<ReferenceWriterAdaptor>(image, std::move(writer));
}
+std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteMethodHandle16(
+ MutableBufferView image) {
+ auto writer =
+ base::BindRepeating(WriteTargetIndex<uint16_t>, method_handle_map_item_,
+ sizeof(dex::MethodHandleItem));
+ return std::make_unique<ReferenceWriterAdaptor>(image, std::move(writer));
+}
+
std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteRelCode8(
MutableBufferView image) {
auto writer = base::BindRepeating([](Reference ref, MutableBufferView image) {
diff --git a/disassembler_dex.h b/disassembler_dex.h
index e75d13e..8e739d0 100644
--- a/disassembler_dex.h
+++ b/disassembler_dex.h
@@ -33,7 +33,7 @@ class DisassemblerDex : public Disassembler {
kMethodId,
// kClassDef, // Unused
kCallSiteId,
- // kMethodHandle, // Unused
+ kMethodHandle,
kTypeList,
kAnnotationSetRefList,
kAnnotionSet,
@@ -83,6 +83,8 @@ class DisassemblerDex : public Disassembler {
kCodeToCallSiteId, // kCallSiteId
+ kCodeToMethodHandle, // kMethodHandle
+
kProtoIdToParametersTypeList, // kTypeList
kClassDefToInterfacesTypeList,
@@ -220,6 +222,8 @@ class DisassemblerDex : public Disassembler {
offset_t hi);
std::unique_ptr<ReferenceReader> MakeReadCodeToCallSiteId16(offset_t lo,
offset_t hi);
+ std::unique_ptr<ReferenceReader> MakeReadCodeToMethodHandle16(offset_t lo,
+ offset_t hi);
std::unique_ptr<ReferenceReader> MakeReadCodeToRelCode8(offset_t lo,
offset_t hi);
std::unique_ptr<ReferenceReader> MakeReadCodeToRelCode16(offset_t lo,
@@ -240,6 +244,8 @@ class DisassemblerDex : public Disassembler {
std::unique_ptr<ReferenceWriter> MakeWriteMethodId32(MutableBufferView image);
std::unique_ptr<ReferenceWriter> MakeWriteCallSiteId16(
MutableBufferView image);
+ std::unique_ptr<ReferenceWriter> MakeWriteMethodHandle16(
+ MutableBufferView image);
std::unique_ptr<ReferenceWriter> MakeWriteRelCode8(MutableBufferView image);
std::unique_ptr<ReferenceWriter> MakeWriteRelCode16(MutableBufferView image);
std::unique_ptr<ReferenceWriter> MakeWriteRelCode32(MutableBufferView image);
diff --git a/testdata/const-method-type-min.smali b/testdata/const-method-type-min.smali
new file mode 100644
index 0000000..8a0f632
--- /dev/null
+++ b/testdata/const-method-type-min.smali
@@ -0,0 +1,16 @@
+# Tests const-method-type added in DEX version 39.
+
+# Compile using smali: https://github.com/JesusFreke/smali
+# java -jar smali.jar assemble const-method-type.smali --api 28
+
+.class public LConstMethodTypeTest;
+.super Ljava/lang/Object;
+
+.method public test(I)V
+ .registers 4
+ const-method-type v0, ()I
+ const-method-type v1, (C)V
+ const-method-type v2, (I)V
+ const-method-type v3, (I)I
+ return-void
+.end method
diff --git a/type_dex.h b/type_dex.h
index e0ccc28..ee61ecd 100644
--- a/type_dex.h
+++ b/type_dex.h
@@ -12,7 +12,7 @@ namespace dex {
// Contains types that models DEX executable format data structures.
// See https://source.android.com/devices/tech/dalvik/dex-format
-// The supported versions are 035, 037, and 038.
+// The supported versions are 035, 037, 038, and 039.
enum class FormatId : uint8_t {
b, // 22b.
@@ -114,6 +114,8 @@ constexpr Instruction kByteCode[] = {
{0xFB, 4, FormatId::c},
{0xFC, 3, FormatId::c},
{0xFD, 3, FormatId::c},
+ {0xFE, 2, FormatId::c},
+ {0xFF, 2, FormatId::c},
};
// Supported by MSVC, g++, and clang++. Ensures no gaps in packing.