diff options
author | Ian Rogers <irogers@google.com> | 2014-09-25 01:55:35 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-09-25 01:55:35 +0000 |
commit | c5c71bfa21aee5ad05217af57e94a0263c4eef1d (patch) | |
tree | 8fa9a003aed0ab98e196ed91338d936efdbadeb7 | |
parent | 9961929db4fce2143df10df60fa29cc8ee7b00d7 (diff) | |
parent | 9bc6199a9a6e140102951f6f38845b43b561af83 (diff) | |
download | art-c5c71bfa21aee5ad05217af57e94a0263c4eef1d.zip art-c5c71bfa21aee5ad05217af57e94a0263c4eef1d.tar.gz art-c5c71bfa21aee5ad05217af57e94a0263c4eef1d.tar.bz2 |
Merge "ART: Reject branch/switch/throw to move-result."
-rw-r--r-- | runtime/verifier/method_verifier.cc | 22 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 15 |
2 files changed, 35 insertions, 2 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index f28d488..45e8b6a 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -650,6 +650,11 @@ bool MethodVerifier::ScanTryCatchBlocks() { << "exception handler starts at bad address (" << dex_pc << ")"; return false; } + if (!CheckNotMoveResult(code_item_->insns_, dex_pc)) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) + << "exception handler begins with move-result* (" << dex_pc << ")"; + return false; + } insn_flags_[dex_pc].SetBranchTarget(); // Ensure exception types are resolved so that they don't need resolution to be delivered, // unresolved exception types will be ignored by exception delivery @@ -2766,7 +2771,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { return false; } DCHECK_EQ(isConditional, (opcode_flags & Instruction::kContinue) != 0); - if (!CheckNotMoveException(code_item_->insns_, work_insn_idx_ + branch_target)) { + if (!CheckNotMoveExceptionOrMoveResult(code_item_->insns_, work_insn_idx_ + branch_target)) { return false; } /* update branch target, set "changed" if appropriate */ @@ -2812,7 +2817,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16); abs_offset = work_insn_idx_ + offset; DCHECK_LT(abs_offset, code_item_->insns_size_in_code_units_); - if (!CheckNotMoveException(code_item_->insns_, abs_offset)) { + if (!CheckNotMoveExceptionOrMoveResult(code_item_->insns_, abs_offset)) { return false; } if (!UpdateRegisters(abs_offset, work_line_.get(), false)) { @@ -4001,6 +4006,19 @@ bool MethodVerifier::CheckNotMoveException(const uint16_t* insns, int insn_idx) return true; } +bool MethodVerifier::CheckNotMoveResult(const uint16_t* insns, int insn_idx) { + if (((insns[insn_idx] & 0xff) >= Instruction::MOVE_RESULT) && + ((insns[insn_idx] & 0xff) <= Instruction::MOVE_RESULT_OBJECT)) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid use of move-result*"; + return false; + } + return true; +} + +bool MethodVerifier::CheckNotMoveExceptionOrMoveResult(const uint16_t* insns, int insn_idx) { + return (CheckNotMoveException(insns, insn_idx) && CheckNotMoveResult(insns, insn_idx)); +} + bool MethodVerifier::UpdateRegisters(uint32_t next_insn, RegisterLine* merge_line, bool update_merge_line) { bool changed = true; diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 87acb20..9f5efe8 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -612,6 +612,21 @@ class MethodVerifier { bool CheckNotMoveException(const uint16_t* insns, int insn_idx); /* + * Verify that the target instruction is not "move-result". It is important that we cannot + * branch to move-result instructions, but we have to make this a distinct check instead of + * adding it to CheckNotMoveException, because it is legal to continue into "move-result" + * instructions - as long as the previous instruction was an invoke, which is checked elsewhere. + */ + bool CheckNotMoveResult(const uint16_t* insns, int insn_idx); + + /* + * Verify that the target instruction is not "move-result" or "move-exception". This is to + * be used when checking branch and switch instructions, but not instructions that can + * continue. + */ + bool CheckNotMoveExceptionOrMoveResult(const uint16_t* insns, int insn_idx); + + /* * Control can transfer to "next_insn". Merge the registers from merge_line into the table at * next_insn, and set the changed flag on the target address if any of the registers were changed. * In the case of fall-through, update the merge line on a change as its the working line for the |