diff options
author | ckitagawa <ckitagawa@chromium.org> | 2021-09-07 21:12:21 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2021-09-07 14:22:35 -0700 |
commit | 1269b5c6a8a1275b7dfdb7ec349f1990bc7c5d77 (patch) | |
tree | 5e5fb506f823182f1e6a11042a1119ec75925392 /disassembler_dex.cc | |
parent | 737d35c6383995ae4d474cd975aebf92aaf73393 (diff) | |
download | zucchini-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
Diffstat (limited to 'disassembler_dex.cc')
-rw-r--r-- | disassembler_dex.cc | 54 |
1 files changed, 45 insertions, 9 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) { |