summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/dex_file.cc1
-rw-r--r--runtime/stack.cc6
-rw-r--r--runtime/verifier/method_verifier.cc11
-rw-r--r--runtime/verifier/register_line.cc4
-rw-r--r--runtime/verifier/register_line.h2
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_);