summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2017-10-31 09:58:07 -0700
committer Mathieu Chartier <mathieuc@google.com> 2017-11-01 10:34:30 -0700
commit176190cbf621f867b0cfcabdec8645fc97065567 (patch)
treedd0d797e7acb1ef3bfdb450b168fc7c6db318225
parent62540e3cc58abde95e147210d584614651d858b5 (diff)
Make SafeDexInstructionIterator more robust
Make operator++ set the error state when if incrementing would go past the end of the code region. Added test in CodeItemOverrun. Bug: 67104794 Test: test-art-host Change-Id: I7b27a1ddb60aaae08ae9ed4ba8762ce2a7746770
-rw-r--r--dexlayout/dexlayout_test.cc7
-rw-r--r--runtime/dex_instruction_iterator.h11
2 files changed, 15 insertions, 3 deletions
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index cdd0219ef3..38d3c6ec07 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -727,6 +727,13 @@ TEST_F(DexLayoutTest, CodeItemOverrun) {
const_cast<Instruction*>(last_instruction.Inst())->SetOpcode(
Instruction::CONST_STRING_JUMBO);
mutated_successfully = true;
+ // Test that the safe iterator doesn't go past the end.
+ SafeDexInstructionIterator it2(instructions.begin(), instructions.end());
+ while (!it2.IsErrorState()) {
+ ++it2;
+ }
+ EXPECT_TRUE(it2 == last_instruction);
+ EXPECT_TRUE(it2 < instructions.end());
}
}
}
diff --git a/runtime/dex_instruction_iterator.h b/runtime/dex_instruction_iterator.h
index afa8d4aad3..9e4dea34bb 100644
--- a/runtime/dex_instruction_iterator.h
+++ b/runtime/dex_instruction_iterator.h
@@ -123,11 +123,16 @@ class SafeDexInstructionIterator : public DexInstructionIteratorBase {
const size_t size_code_units = Inst()->CodeUnitsRequiredForSizeComputation();
const size_t available = reinterpret_cast<const uint16_t*>(end_) -
reinterpret_cast<const uint16_t*>(Inst());
- if (size_code_units > available) {
+ if (UNLIKELY(size_code_units > available)) {
error_state_ = true;
- } else {
- inst_ = inst_->Next();
+ return *this;
}
+ const size_t instruction_size = inst_->SizeInCodeUnits();
+ if (UNLIKELY(instruction_size > available)) {
+ error_state_ = true;
+ return *this;
+ }
+ inst_ = inst_->RelativeAt(instruction_size);
return *this;
}