summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andreas Gampe <agampe@google.com> 2014-04-17 21:10:52 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2014-04-17 21:10:53 +0000
commitb99985a089e23929c920201c14875b51c5b6217e (patch)
tree7ce86f1f277834802cfea486e5aa592e6cc1cd04
parent425640d6fac3432a44e236a002e8401a7cd59c5c (diff)
parent639815628cf52a4a944a4322cb09da37cded2de9 (diff)
Merge "Fix a class-loading bug in the verifier when throwing NPE"
-rw-r--r--runtime/verifier/method_verifier.cc16
-rw-r--r--runtime/verifier/reg_type_cache.cc24
-rw-r--r--runtime/verifier/reg_type_cache.h6
3 files changed, 25 insertions, 21 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 5a9d27cea6..dbde7c7632 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -392,7 +392,7 @@ mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(mirror::ArtMethod* m
SirtRef<mirror::DexCache> dex_cache(self, mh.GetDexCache());
SirtRef<mirror::ClassLoader> class_loader(self, mh.GetClassLoader());
MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(),
- mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false,
+ mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true,
true);
return verifier.FindInvokedMethodAtDexPc(dex_pc);
}
@@ -3119,18 +3119,22 @@ mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst
inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
const RegType& actual_arg_type = reg_line->GetInvocationThis(inst, is_range);
if (actual_arg_type.IsConflict()) { // GetInvocationThis failed.
- return NULL;
+ return nullptr;
} else if (actual_arg_type.IsZero()) { // Invoke on "null" instance: we can't go further.
- return NULL;
+ return nullptr;
}
mirror::Class* this_class = NULL;
if (!actual_arg_type.IsUnresolvedTypes()) {
this_class = actual_arg_type.GetClass();
} else {
const std::string& descriptor(actual_arg_type.GetDescriptor());
- // TODO: Precise or not?
- this_class = reg_types_.FromDescriptor(class_loader_->get(), descriptor.c_str(),
- false).GetClass();
+ // Try to resolve type.
+ const RegType& resolved_arg_type = reg_types_.FromDescriptor(class_loader_->get(),
+ descriptor.c_str(), false);
+ if (!resolved_arg_type.HasClass()) {
+ return nullptr; // Resolution failed.
+ }
+ this_class = resolved_arg_type.GetClass();
if (this_class == NULL) {
Thread* self = Thread::Current();
self->ClearException();
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 9dd57b880b..111e8679c0 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -156,15 +156,6 @@ mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassL
return klass;
}
-void RegTypeCache::ClearException() {
- if (can_load_classes_) {
- DCHECK(Thread::Current()->IsExceptionPending());
- Thread::Current()->ClearException();
- } else {
- DCHECK(!Thread::Current()->IsExceptionPending());
- }
-}
-
const RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descriptor,
bool precise) {
// Try looking up the class in the cache first.
@@ -199,7 +190,12 @@ const RegType& RegTypeCache::From(mirror::ClassLoader* loader, const char* descr
} else { // Class not resolved.
// We tried loading the class and failed, this might get an exception raised
// so we want to clear it before we go on.
- ClearException();
+ if (can_load_classes_) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ Thread::Current()->ClearException();
+ } else {
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ }
if (IsValidDescriptor(descriptor)) {
RegType* entry = new UnresolvedReferenceType(descriptor, entries_.size());
entries_.push_back(entry);
@@ -238,6 +234,14 @@ const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* kl
}
}
+RegTypeCache::RegTypeCache(bool can_load_classes) : can_load_classes_(can_load_classes) {
+ if (kIsDebugBuild && can_load_classes) {
+ Thread::Current()->AssertThreadSuspensionIsAllowable();
+ }
+ entries_.reserve(64);
+ FillPrimitiveAndSmallConstantTypes();
+}
+
RegTypeCache::~RegTypeCache() {
CHECK_LE(primitive_count_, entries_.size());
// Delete only the non primitive types.
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index 4cc7e61275..70d5f0731c 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -38,10 +38,7 @@ class RegType;
class RegTypeCache {
public:
- explicit RegTypeCache(bool can_load_classes) : can_load_classes_(can_load_classes) {
- entries_.reserve(64);
- FillPrimitiveAndSmallConstantTypes();
- }
+ explicit RegTypeCache(bool can_load_classes);
~RegTypeCache();
static void Init() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (!RegTypeCache::primitive_initialized_) {
@@ -152,7 +149,6 @@ class RegTypeCache {
void FillPrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void ClearException();
bool MatchDescriptor(size_t idx, const char* descriptor, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise)