summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-06-23 14:18:17 -0700
committerAndreas Gampe <agampe@google.com>2015-06-23 16:03:37 -0700
commita497d1cf500f3b06fb401c33e21d38f1bd0026ad (patch)
tree758f9f31814c674d3db128b1dc587d32afccdcba /runtime
parent67b00a12a07fb7c98477d9ca9a25522480fccea6 (diff)
downloadart-a497d1cf500f3b06fb401c33e21d38f1bd0026ad.zip
art-a497d1cf500f3b06fb401c33e21d38f1bd0026ad.tar.gz
art-a497d1cf500f3b06fb401c33e21d38f1bd0026ad.tar.bz2
ART: Follow-up to 507cc6f83bf6379728f2dd20391f2ed5fbfe6371
Do not trigger DCHECK aborts for final and abstract classes when they are used from other classes. Instead issue a soft error that leads to a runtime failure. Bug: 21873151 (cherry picked from commit f23f33de8b3e9abd16720e0f48d43d63d41dee16) Change-Id: Ie5251a176722811b3c74585222874313a53f7e02
Diffstat (limited to 'runtime')
-rw-r--r--runtime/verifier/method_verifier.cc55
-rw-r--r--runtime/verifier/method_verifier.h8
2 files changed, 41 insertions, 22 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 6c55356..5436100 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2401,9 +2401,9 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
StackHandleScope<1> hs(self_);
mirror::Class* return_type_class = called_method->GetReturnType(can_load_classes_);
if (return_type_class != nullptr) {
- return_type = &reg_types_.FromClass(called_method->GetReturnTypeDescriptor(),
- return_type_class,
- return_type_class->CannotBeAssignedFromOtherTypes());
+ return_type = &FromClass(called_method->GetReturnTypeDescriptor(),
+ return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
self_->ClearException();
@@ -2446,9 +2446,9 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
StackHandleScope<1> hs(self_);
mirror::Class* return_type_class = called_method->GetReturnType(can_load_classes_);
if (return_type_class != nullptr) {
- return_type = &reg_types_.FromClass(return_type_descriptor,
- return_type_class,
- return_type_class->CannotBeAssignedFromOtherTypes());
+ return_type = &FromClass(return_type_descriptor,
+ return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
self_->ClearException();
@@ -3164,7 +3164,7 @@ const RegType& MethodVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
const RegType& referrer = GetDeclaringClass();
mirror::Class* klass = dex_cache_->GetResolvedType(class_idx);
const RegType& result = klass != nullptr ?
- reg_types_.FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes()) :
+ FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes()) :
reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
if (result.IsConflict()) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "accessing broken descriptor '" << descriptor
@@ -3380,8 +3380,8 @@ ArtMethod* MethodVerifier::VerifyInvocationArgsFromIterator(
if (res_method != nullptr) {
mirror::Class* klass = res_method->GetDeclaringClass();
std::string temp;
- res_method_class = &reg_types_.FromClass(klass->GetDescriptor(&temp), klass,
- klass->CannotBeAssignedFromOtherTypes());
+ res_method_class = &FromClass(klass->GetDescriptor(&temp), klass,
+ klass->CannotBeAssignedFromOtherTypes());
} else {
const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
const uint16_t class_idx = dex_file_->GetMethodId(method_idx).class_idx_;
@@ -3622,8 +3622,7 @@ ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instruction* inst,
mirror::Class* klass = res_method->GetDeclaringClass();
std::string temp;
const RegType& res_method_class =
- reg_types_.FromClass(klass->GetDescriptor(&temp), klass,
- klass->CannotBeAssignedFromOtherTypes());
+ FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
@@ -3933,8 +3932,8 @@ ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_id
} else {
mirror::Class* klass = field->GetDeclaringClass();
const RegType& field_klass =
- reg_types_.FromClass(dex_file_->GetFieldDeclaringClassDescriptor(field_id),
- klass, klass->CannotBeAssignedFromOtherTypes());
+ FromClass(dex_file_->GetFieldDeclaringClassDescriptor(field_id),
+ klass, klass->CannotBeAssignedFromOtherTypes());
if (obj_type.IsUninitializedTypes() &&
(!IsConstructor() || GetDeclaringClass().Equals(obj_type) ||
!field_klass.Equals(GetDeclaringClass()))) {
@@ -3984,8 +3983,8 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType&
mirror::Class* field_type_class =
can_load_classes_ ? field->GetType<true>() : field->GetType<false>();
if (field_type_class != nullptr) {
- field_type = &reg_types_.FromClass(field->GetTypeDescriptor(), field_type_class,
- field_type_class->CannotBeAssignedFromOtherTypes());
+ field_type = &FromClass(field->GetTypeDescriptor(), field_type_class,
+ field_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
self_->ClearException();
@@ -4096,8 +4095,8 @@ void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegTy
field->GetType<false>();
if (field_type_class != nullptr) {
- field_type = &reg_types_.FromClass(field->GetTypeDescriptor(), field_type_class,
- field_type_class->CannotBeAssignedFromOtherTypes());
+ field_type = &FromClass(field->GetTypeDescriptor(), field_type_class,
+ field_type_class->CannotBeAssignedFromOtherTypes());
} else {
Thread* self = Thread::Current();
DCHECK(!can_load_classes_ || self->IsExceptionPending());
@@ -4289,9 +4288,9 @@ const RegType& MethodVerifier::GetMethodReturnType() {
if (mirror_method_ != nullptr) {
mirror::Class* return_type_class = mirror_method_->GetReturnType(can_load_classes_);
if (return_type_class != nullptr) {
- return_type_ = &reg_types_.FromClass(mirror_method_->GetReturnTypeDescriptor(),
- return_type_class,
- return_type_class->CannotBeAssignedFromOtherTypes());
+ return_type_ = &FromClass(mirror_method_->GetReturnTypeDescriptor(),
+ return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
self_->ClearException();
@@ -4315,8 +4314,8 @@ const RegType& MethodVerifier::GetDeclaringClass() {
= dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
if (mirror_method_ != nullptr) {
mirror::Class* klass = mirror_method_->GetDeclaringClass();
- declaring_class_ = &reg_types_.FromClass(descriptor, klass,
- klass->CannotBeAssignedFromOtherTypes());
+ declaring_class_ = &FromClass(descriptor, klass,
+ klass->CannotBeAssignedFromOtherTypes());
} else {
declaring_class_ = &reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
}
@@ -4416,5 +4415,17 @@ void MethodVerifier::VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
reg_types_.VisitRoots(visitor, root_info);
}
+const RegType& MethodVerifier::FromClass(const char* descriptor,
+ mirror::Class* klass,
+ bool precise) {
+ DCHECK(klass != nullptr);
+ if (precise && !klass->IsInstantiable() && !klass->IsPrimitive()) {
+ Fail(VerifyError::VERIFY_ERROR_NO_CLASS) << "Could not create precise reference for "
+ << "non-instantiable klass " << descriptor;
+ precise = false;
+ }
+ return reg_types_.FromClass(descriptor, klass, precise);
+}
+
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 873b8ab..cd691a3 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -660,6 +660,14 @@ class MethodVerifier {
const RegType& DetermineCat1Constant(int32_t value, bool precise)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Try to create a register type from the given class. In case a precise type is requested, but
+ // the class is not instantiable, a soft error (of type NO_CLASS) will be enqueued and a
+ // non-precise reference will be returned.
+ // Note: we reuse NO_CLASS as this will throw an exception at runtime, when the failing class is
+ // actually touched.
+ const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// The thread we're verifying on.
Thread* const self_;