diff options
author | Brian Carlstrom <bdc@google.com> | 2011-11-02 17:12:02 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-11-02 17:12:02 -0700 |
commit | 0b3a52a3ec75f1a248e040b267776c68d016e940 (patch) | |
tree | 4f639e995a2dc081a9a5f6e2e489d722b122eb69 /src | |
parent | ff9146509a092d23f6837525a24831a0e3fb5155 (diff) | |
parent | 55d249fc84c313aa071a717f53f9164fa49e2a59 (diff) | |
download | art-0b3a52a3ec75f1a248e040b267776c68d016e940.zip art-0b3a52a3ec75f1a248e040b267776c68d016e940.tar.gz art-0b3a52a3ec75f1a248e040b267776c68d016e940.tar.bz2 |
Merge "Fix monitor stack depth bug, allow unresolved field in put." into dalvik-dev
Diffstat (limited to 'src')
-rw-r--r-- | src/dex_verifier.cc | 37 | ||||
-rw-r--r-- | src/dex_verifier.h | 10 |
2 files changed, 32 insertions, 15 deletions
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 @@ void RegisterLine::PushMonitor(uint32_t reg_idx, int32_t insn_idx) { 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 @@ void RegisterLine::PopMonitor(uint32_t reg_idx) { } 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 @@ bool RegisterLine::MergeRegisters(const RegisterLine* incoming_line) { 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::VerifyISGet(const Instruction::DecodedInstruction& dec_insn, 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) + 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(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; + return; + } } - const RegType& field_type = - reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(), - field->GetTypeDescriptor()); 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 @@ class RegisterLine { 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 @@ class RegisterLine { // 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 |