aboutsummaryrefslogtreecommitdiff
path: root/disassembler_dex.cc
diff options
context:
space:
mode:
authorCalder Kitagawa <ckitagawa@chromium.org>2018-07-04 20:44:27 +0000
committerCopybara-Service <copybara-worker@google.com>2021-07-25 20:07:32 -0700
commit40a74cc5a9ef13950080571497f8b0e3b36d6599 (patch)
tree757aa862ad5a3436c0f9ae14b70476de03174d9f /disassembler_dex.cc
parentcd8becf50509b9846b9baf3a5b8239eb6dfe4f4f (diff)
downloadzucchini-40a74cc5a9ef13950080571497f8b0e3b36d6599.tar.gz
[Zucchini] Enforce valid casts on Rel codes
The MakeWriteRelCodeXX used base::checked_cast which results in a crash. To fail gracefully we instead use base::CheckedNumeric. The appearance of this bug results from the input files being bad resulting in the output from gen also being bad which then propagates to the apply step. Bug: 860128 Change-Id: I38fc91b0a1495ce0c337d778fb51cfe56537e766 Reviewed-on: https://chromium-review.googlesource.com/1126178 Reviewed-by: Samuel Huang <huangs@chromium.org> Commit-Queue: Calder Kitagawa <ckitagawa@chromium.org> Cr-Commit-Position: refs/heads/master@{#572648} NOKEYCHECK=True GitOrigin-RevId: 2d78c3c15a71b517d3ef226010f1cfc4b13e5ea1
Diffstat (limited to 'disassembler_dex.cc')
-rw-r--r--disassembler_dex.cc43
1 files changed, 31 insertions, 12 deletions
diff --git a/disassembler_dex.cc b/disassembler_dex.cc
index 01d5e98..8a1b339 100644
--- a/disassembler_dex.cc
+++ b/disassembler_dex.cc
@@ -1446,12 +1446,17 @@ std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteMethodId32(
std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteRelCode8(
MutableBufferView image) {
auto writer = base::BindRepeating([](Reference ref, MutableBufferView image) {
- ptrdiff_t byte_diff = static_cast<ptrdiff_t>(ref.target) - ref.location;
- DCHECK_EQ(0, byte_diff % kInstrUnitSize);
+ ptrdiff_t unsafe_byte_diff =
+ static_cast<ptrdiff_t>(ref.target) - ref.location;
+ DCHECK_EQ(0, unsafe_byte_diff % kInstrUnitSize);
// |delta| is relative to start of instruction, which is 1 unit before
// |ref.location|. The subtraction above removed too much, so +1 to fix.
- ptrdiff_t delta = (byte_diff / kInstrUnitSize) + 1;
- image.write<int8_t>(ref.location, base::checked_cast<int8_t>(delta));
+ base::CheckedNumeric<int8_t> delta((unsafe_byte_diff / kInstrUnitSize) + 1);
+ if (!delta.IsValid()) {
+ LOG(ERROR) << "Invalid reference at: " << AsHex<8>(ref.location);
+ return;
+ }
+ image.write<int8_t>(ref.location, delta.ValueOrDie());
});
return std::make_unique<ReferenceWriterAdaptor>(image, std::move(writer));
}
@@ -1459,12 +1464,18 @@ std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteRelCode8(
std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteRelCode16(
MutableBufferView image) {
auto writer = base::BindRepeating([](Reference ref, MutableBufferView image) {
- ptrdiff_t byte_diff = static_cast<ptrdiff_t>(ref.target) - ref.location;
- DCHECK_EQ(0, byte_diff % kInstrUnitSize);
+ ptrdiff_t unsafe_byte_diff =
+ static_cast<ptrdiff_t>(ref.target) - ref.location;
+ DCHECK_EQ(0, unsafe_byte_diff % kInstrUnitSize);
// |delta| is relative to start of instruction, which is 1 unit before
// |ref.location|. The subtraction above removed too much, so +1 to fix.
- ptrdiff_t delta = (byte_diff / kInstrUnitSize) + 1;
- image.write<int16_t>(ref.location, base::checked_cast<int16_t>(delta));
+ base::CheckedNumeric<int16_t> delta((unsafe_byte_diff / kInstrUnitSize) +
+ 1);
+ if (!delta.IsValid()) {
+ LOG(ERROR) << "Invalid reference at: " << AsHex<8>(ref.location);
+ return;
+ }
+ image.write<int16_t>(ref.location, delta.ValueOrDie());
});
return std::make_unique<ReferenceWriterAdaptor>(image, std::move(writer));
}
@@ -1472,10 +1483,18 @@ std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteRelCode16(
std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteRelCode32(
MutableBufferView image) {
auto writer = base::BindRepeating([](Reference ref, MutableBufferView image) {
- ptrdiff_t byte_diff = static_cast<ptrdiff_t>(ref.target) - ref.location;
- DCHECK_EQ(0, byte_diff % kInstrUnitSize);
- ptrdiff_t delta = (byte_diff / kInstrUnitSize) + 1;
- image.write<int32_t>(ref.location, base::checked_cast<int32_t>(delta));
+ ptrdiff_t unsafe_byte_diff =
+ static_cast<ptrdiff_t>(ref.target) - ref.location;
+ DCHECK_EQ(0, unsafe_byte_diff % kInstrUnitSize);
+ // |delta| is relative to start of instruction, which is 1 unit before
+ // |ref.location|. The subtraction above removed too much, so +1 to fix.
+ base::CheckedNumeric<int32_t> delta((unsafe_byte_diff / kInstrUnitSize) +
+ 1);
+ if (!delta.IsValid()) {
+ LOG(ERROR) << "Invalid reference at: " << AsHex<8>(ref.location);
+ return;
+ }
+ image.write<int32_t>(ref.location, delta.ValueOrDie());
});
return std::make_unique<ReferenceWriterAdaptor>(image, std::move(writer));
}