diff options
-rw-r--r-- | src/class_linker.cc | 29 | ||||
-rw-r--r-- | src/dex_verifier.cc | 6 | ||||
-rw-r--r-- | src/dex_verifier.h | 14 |
3 files changed, 32 insertions, 17 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index e32f8a53a9..04a368d81a 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -59,13 +59,12 @@ void ThrowLinkageError(const char* fmt, ...) { va_end(args); } -void ThrowNoSuchMethodError(const char* kind, - Class* c, const StringPiece& name, const StringPiece& signature) { +void ThrowNoSuchMethodError(bool is_direct, Class* c, const StringPiece& name, + const StringPiece& signature) { ClassHelper kh(c); std::ostringstream msg; - msg << "no " << kind << " method " << name << "." << signature - << " in class " << kh.GetDescriptor() - << " or its superclasses"; + msg << "no " << (is_direct ? "direct" : "virtual") << " method " << name << "." << signature + << " in class " << kh.GetDescriptor() << " or its superclasses"; std::string location(kh.GetLocation()); if (!location.empty()) { msg << " (defined in " << location << ")"; @@ -73,6 +72,19 @@ void ThrowNoSuchMethodError(const char* kind, Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str()); } +void ThrowNoSuchFieldError(bool is_static, Class* c, const StringPiece& type, + const StringPiece& name) { + ClassHelper kh(c); + std::ostringstream msg; + msg << "no " << (is_static ? "static": "instance") << " field " << name << " of type " << type + << " in class " << kh.GetDescriptor() << " or its superclasses"; + std::string location(kh.GetLocation()); + if (!location.empty()) { + msg << " (defined in " << location << ")"; + } + Thread::Current()->ThrowNewException("Ljava/lang/NoSuchFieldError;", msg.str().c_str()); +} + void ThrowEarlierClassFailure(Class* c) { /* * The class failed to initialize on a previous attempt, so we want to throw @@ -2770,7 +2782,7 @@ Method* ClassLinker::ResolveMethod(const DexFile& dex_file, if (resolved != NULL) { dex_cache->SetResolvedMethod(method_idx, resolved); } else { - ThrowNoSuchMethodError(is_direct ? "direct" : "virtual", klass, name, signature); + ThrowNoSuchMethodError(is_direct, klass, name, signature); } return resolved; } @@ -2787,6 +2799,7 @@ Field* ClassLinker::ResolveField(const DexFile& dex_file, const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); Class* klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader); if (klass == NULL) { + DCHECK(Thread::Current()->IsExceptionPending()); return NULL; } @@ -2800,9 +2813,7 @@ Field* ClassLinker::ResolveField(const DexFile& dex_file, if (resolved != NULL) { dex_cache->SetResolvedField(field_idx, resolved); } else { - // TODO: this check fails when the app class path contains a class from the boot class path - CHECK(Thread::Current()->IsExceptionPending()) - << PrettyClass(klass) << " " << name << " " << type << " " << is_static; + ThrowNoSuchFieldError(is_static, klass, type, name); } return resolved; } diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc index f6bdd7d2f2..90940679d1 100644 --- a/src/dex_verifier.cc +++ b/src/dex_verifier.cc @@ -2033,6 +2033,10 @@ bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { bool is_checkcast = dec_insn.opcode_ == Instruction::CHECK_CAST; const RegType& res_type = ResolveClassAndCheckAccess(is_checkcast ? dec_insn.vB_ : dec_insn.vC_); + if (res_type.IsUnknown()) { + CHECK_NE(failure_, VERIFY_ERROR_NONE); + break; // couldn't resolve class + } // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved const RegType& orig_type = work_line_->GetRegisterType(is_checkcast ? dec_insn.vA_ : dec_insn.vB_); @@ -3028,7 +3032,7 @@ Method* DexVerifier::ResolveMethodAndCheckAccess(uint32_t method_idx, bool is_di if (res_method == NULL) { const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx); const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_); - if(klass_type.IsUnresolvedTypes()) { + if(klass_type.IsUnresolvedTypes() || klass_type.IsUnknown()) { return NULL; // Can't resolve Class so no more to do here } Class* klass = klass_type.GetClass(); diff --git a/src/dex_verifier.h b/src/dex_verifier.h index 201cd2b3b1..5b2f54e28a 100644 --- a/src/dex_verifier.h +++ b/src/dex_verifier.h @@ -707,14 +707,14 @@ class RegisterLine { void CopyRegToLockDepth(size_t dst, size_t src) { if (reg_to_lock_depths_.count(src) > 0) { - uint32_t depths = reg_to_lock_depths_[src]; + uint64_t depths = reg_to_lock_depths_[src]; reg_to_lock_depths_[dst] = depths; } } bool IsSetLockDepth(size_t reg, size_t depth) { if (reg_to_lock_depths_.count(reg) > 0) { - uint32_t depths = reg_to_lock_depths_[reg]; + uint64_t depths = reg_to_lock_depths_[reg]; return (depths & (1 << depth)) != 0; } else { return false; @@ -722,9 +722,9 @@ class RegisterLine { } void SetRegToLockDepth(size_t reg, size_t depth) { - CHECK_LT(depth, 32u); + CHECK_LT(depth, 64u); DCHECK(!IsSetLockDepth(reg, depth)); - uint32_t depths; + uint64_t depths; if (reg_to_lock_depths_.count(reg) > 0) { depths = reg_to_lock_depths_[reg]; depths = depths | (1 << depth); @@ -735,9 +735,9 @@ class RegisterLine { } void ClearRegToLockDepth(size_t reg, size_t depth) { - CHECK_LT(depth, 32u); + CHECK_LT(depth, 64u); DCHECK(IsSetLockDepth(reg, depth)); - uint32_t depths = reg_to_lock_depths_[reg]; + uint64_t depths = reg_to_lock_depths_[reg]; depths = depths ^ (1 << depth); if (depths != 0) { reg_to_lock_depths_[reg] = depths; @@ -766,7 +766,7 @@ class RegisterLine { // 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 - std::map<uint32_t, uint32_t> reg_to_lock_depths_; + std::map<uint32_t, uint64_t> reg_to_lock_depths_; }; std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs); |