Fix monitor stack depth bug, allow unresolved field in put.
Change-Id: I9625fc24c49e4d8e453ff545c50b0c64c0f1ae3b
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 5ab21bb..3ad9996 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -766,7 +766,7 @@
verifier_->Fail(VERIFY_ERROR_GENERIC) << "monitor-enter on non-object (" << reg_type << ")";
} else {
SetRegToLockDepth(reg_idx, monitors_.size());
- monitors_.push(insn_idx);
+ monitors_.push_back(insn_idx);
}
}
@@ -777,7 +777,7 @@
} else if (monitors_.empty()) {
verifier_->Fail(VERIFY_ERROR_GENERIC) << "monitor-exit stack underflow";
} else {
- monitors_.pop();
+ monitors_.pop_back();
if(!IsSetLockDepth(reg_idx, monitors_.size())) {
// Bug 3215458: Locks and unlocks are on objects, if that object is a literal then before
// format "036" the constant collector may create unlocks on the same object but referenced
@@ -812,7 +812,7 @@
line_[idx] = new_type.GetId();
}
}
- if(monitors_ != incoming_line->monitors_) {
+ if(monitors_.size() != incoming_line->monitors_.size()) {
verifier_->Fail(VERIFY_ERROR_GENERIC) << "mismatched stack depths (depth="
<< MonitorStackDepth() << ", incoming depth=" << incoming_line->MonitorStackDepth() << ")";
} else if (reg_to_lock_depths_ != incoming_line->reg_to_lock_depths_) {
@@ -3407,22 +3407,35 @@
void DexVerifier::VerifyISPut(const Instruction::DecodedInstruction& dec_insn,
const RegType& insn_type, bool is_primitive, bool is_static) {
+ uint32_t field_idx = is_static ? dec_insn.vB_ : dec_insn.vC_;
Field* field;
if (is_static) {
- field = GetStaticField(dec_insn.vB_);
+ field = GetStaticField(field_idx);
} else {
const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
- field = GetInstanceField(object_type, dec_insn.vC_);
+ field = GetInstanceField(object_type, field_idx);
}
- if (field != NULL) {
- if (field->IsFinal() && field->GetDeclaringClass() != method_->GetDeclaringClass()) {
- Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
- << " from other class " << PrettyClass(method_->GetDeclaringClass());
- return;
+ if (failure_ != VERIFY_ERROR_NONE) {
+ work_line_->SetRegisterType(dec_insn.vA_, reg_types_.Unknown());
+ } else {
+ const char* descriptor;
+ const ClassLoader* loader;
+ if (field != NULL) {
+ descriptor = field->GetTypeDescriptor();
+ loader = field->GetDeclaringClass()->GetClassLoader();
+ } else {
+ const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
+ descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
+ loader = method_->GetDeclaringClass()->GetClassLoader();
}
- const RegType& field_type =
- reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(),
- field->GetTypeDescriptor());
+ const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor);
+ if (field != NULL) {
+ if (field->IsFinal() && field->GetDeclaringClass() != method_->GetDeclaringClass()) {
+ Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
+ << " from other class " << PrettyClass(method_->GetDeclaringClass());
+ return;
+ }
+ }
if (is_primitive) {
// Primitive field assignability rules are weaker than regular assignability rules
bool instruction_compatible;
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index dbe92f6..a703cbc 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -11,9 +11,9 @@
#include "stl_util.h"
#include "UniquePtr.h"
+#include <deque>
#include <limits>
#include <map>
-#include <stack>
#include <vector>
namespace art {
@@ -572,13 +572,17 @@
result += GetRegisterType(i).Dump();
result += "],";
}
+ typedef std::deque<uint32_t>::const_iterator It; // TODO: C++0x auto
+ for (It it = monitors_.begin(), end = monitors_.end(); it != end ; ++it) {
+ result += StringPrintf("{%d},", *it);
+ }
return result;
}
void FillWithGarbage() {
memset(line_.get(), 0xf1, num_regs_ * sizeof(uint16_t));
while (!monitors_.empty()) {
- monitors_.pop();
+ monitors_.pop_back();
}
reg_to_lock_depths_.clear();
}
@@ -758,7 +762,7 @@
// Length of reg_types_
const size_t num_regs_;
// A stack of monitor enter locations
- std::stack<uint32_t> monitors_;
+ std::deque<uint32_t> monitors_;
// A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor
// stack we verify that monitor-enter/exit are correctly nested. That is, if there was a
// monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5