diff options
| -rw-r--r-- | runtime/dex_file.cc | 1 | ||||
| -rw-r--r-- | runtime/stack.cc | 6 | ||||
| -rw-r--r-- | runtime/verifier/method_verifier.cc | 11 | ||||
| -rw-r--r-- | runtime/verifier/register_line.cc | 4 | ||||
| -rw-r--r-- | runtime/verifier/register_line.h | 2 |
5 files changed, 16 insertions, 8 deletions
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index cbdc430b8c..aaff0fc6da 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -313,7 +313,6 @@ void DexFile::InitMembers() { method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_); proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_); class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_); - DCHECK_EQ(size_, header_->file_size_) << GetLocation(); } bool DexFile::CheckMagicAndVersion() const { diff --git a/runtime/stack.cc b/runtime/stack.cc index b07a24ef2a..e1a752adb9 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -267,7 +267,11 @@ void StackVisitor::SanityCheckFrame() const { // Frame sanity. size_t frame_size = method->GetFrameSizeInBytes(); CHECK_NE(frame_size, 0u); - CHECK_LT(frame_size, 1024u); + // A rough guess at an upper size we expect to see for a frame. The 256 is + // a dex register limit. The 16 incorporates callee save spills and + // outgoing argument set up. + const size_t kMaxExpectedFrameSize = 256 * sizeof(word) + 16; + CHECK_LE(frame_size, kMaxExpectedFrameSize); size_t return_pc_offset = method->GetReturnPcOffsetInBytes(); CHECK_LT(return_pc_offset, frame_size); } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 9bedf6d88f..eb6e3c3453 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -2819,8 +2819,10 @@ const RegType& MethodVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) { dex_cache_->SetResolvedType(class_idx, result.GetClass()); } // Check if access is allowed. Unresolved types use xxxWithAccessCheck to - // check at runtime if access is allowed and so pass here. - if (!result.IsUnresolvedTypes() && !referrer.IsUnresolvedTypes() && !referrer.CanAccess(result)) { + // check at runtime if access is allowed and so pass here. If result is + // primitive, skip the access check. + if (result.IsNonZeroReferenceTypes() && !result.IsUnresolvedTypes() && + !referrer.IsUnresolvedTypes() && !referrer.CanAccess(result)) { Fail(VERIFY_ERROR_ACCESS_CLASS) << "illegal class access: '" << referrer << "' -> '" << result << "'"; } @@ -3347,7 +3349,6 @@ void MethodVerifier::VerifyAPut(const Instruction* inst, } else if (!array_type.IsArrayTypes()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "not array type " << array_type << " with aput"; } else { - /* verify the class */ const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_); const uint32_t vregA = inst->VRegA_23x(); if (is_primitive) { @@ -3753,6 +3754,10 @@ bool MethodVerifier::UpdateRegisters(uint32_t next_insn, const RegisterLine* mer if (!insn_flags_[next_insn].IsReturn()) { target_line->CopyFromLine(merge_line); } else { + // Verify that the monitor stack is empty on return. + if (!merge_line->VerifyMonitorStackEmpty()) { + return false; + } // For returns we only care about the operand to the return, all other registers are dead. // Initialize them as conflicts so they don't add to GC and deoptimization information. const Instruction* ret_inst = Instruction::At(code_item_->insns_ + next_insn); diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc index 7965c0641e..24a626b277 100644 --- a/runtime/verifier/register_line.cc +++ b/runtime/verifier/register_line.cc @@ -38,7 +38,7 @@ bool RegisterLine::CheckConstructorReturn() const { bool RegisterLine::SetRegisterType(uint32_t vdst, const RegType& new_type) { DCHECK_LT(vdst, num_regs_); if (new_type.IsLowHalf() || new_type.IsHighHalf()) { - verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Expected category1 register type not '" + verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Expected category1 register type not '" << new_type << "'"; return false; } else if (new_type.IsConflict()) { // should only be set during a merge @@ -448,7 +448,7 @@ void RegisterLine::PopMonitor(uint32_t reg_idx) { } } -bool RegisterLine::VerifyMonitorStackEmpty() { +bool RegisterLine::VerifyMonitorStackEmpty() const { if (MonitorStackDepth() != 0) { verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected empty monitor stack"; return false; diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h index f3808776f2..f19dccac17 100644 --- a/runtime/verifier/register_line.h +++ b/runtime/verifier/register_line.h @@ -268,7 +268,7 @@ class RegisterLine { // We expect no monitors to be held at certain points, such a method returns. Verify the stack // is empty, failing and returning false if not. - bool VerifyMonitorStackEmpty(); + bool VerifyMonitorStackEmpty() const; bool MergeRegisters(const RegisterLine* incoming_line) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |