diff options
-rw-r--r-- | runtime/mirror/class.cc | 8 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 17 | ||||
-rw-r--r-- | runtime/verifier/reg_type.cc | 37 | ||||
-rw-r--r-- | runtime/verifier/reg_type.h | 12 |
4 files changed, 70 insertions, 4 deletions
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 9fa6073698..29851a9d4f 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -228,8 +228,12 @@ void Class::DumpClass(std::ostream& os, int flags) { os << " interfaces (" << num_direct_interfaces << "):\n"; for (size_t i = 0; i < num_direct_interfaces; ++i) { Class* interface = GetDirectInterface(self, h_this, i); - const ClassLoader* cl = interface->GetClassLoader(); - os << StringPrintf(" %2zd: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl); + if (interface == nullptr) { + os << StringPrintf(" %2zd: nullptr!\n", i); + } else { + const ClassLoader* cl = interface->GetClassLoader(); + os << StringPrintf(" %2zd: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl); + } } } if (!IsLoaded()) { diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 47e9bf537b..988fc0ed0a 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -1752,8 +1752,21 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { Fail(VERIFY_ERROR_NO_CLASS) << " can't resolve returned type '" << return_type << "' or '" << reg_type << "'"; } else { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning '" << reg_type - << "', but expected from declaration '" << return_type << "'"; + bool soft_error = false; + // Check whether arrays are involved. They will show a valid class status, even + // if their components are erroneous. + if (reg_type.IsArrayTypes() && return_type.IsArrayTypes()) { + return_type.CanAssignArray(reg_type, reg_types_, class_loader_, &soft_error); + if (soft_error) { + Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "array with erroneous component type: " + << reg_type << " vs " << return_type; + } + } + + if (!soft_error) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning '" << reg_type + << "', but expected from declaration '" << return_type << "'"; + } } } } diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 201169f794..97d0cbe17f 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -822,5 +822,42 @@ std::ostream& operator<<(std::ostream& os, const RegType& rhs) { return os; } +bool RegType::CanAssignArray(const RegType& src, RegTypeCache& reg_types, + Handle<mirror::ClassLoader> class_loader, bool* soft_error) const { + if (!IsArrayTypes() || !src.IsArrayTypes()) { + *soft_error = false; + return false; + } + + const RegType& cmp1 = reg_types.GetComponentType(*this, class_loader.Get()); + const RegType& cmp2 = reg_types.GetComponentType(src, class_loader.Get()); + + if (cmp1.IsAssignableFrom(cmp2)) { + return true; + } + if (cmp1.IsUnresolvedTypes()) { + if (cmp2.IsIntegralTypes() || cmp2.IsFloatTypes() || cmp2.IsArrayTypes()) { + *soft_error = false; + return false; + } + *soft_error = true; + return false; + } + if (cmp2.IsUnresolvedTypes()) { + if (cmp1.IsIntegralTypes() || cmp1.IsFloatTypes() || cmp1.IsArrayTypes()) { + *soft_error = false; + return false; + } + *soft_error = true; + return false; + } + if (!cmp1.IsArrayTypes() || !cmp2.IsArrayTypes()) { + *soft_error = false; + return false; + } + return cmp1.CanAssignArray(cmp2, reg_types, class_loader, soft_error); +} + + } // namespace verifier } // namespace art diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h index 73e131eff5..d260650d5b 100644 --- a/runtime/verifier/reg_type.h +++ b/runtime/verifier/reg_type.h @@ -25,6 +25,7 @@ #include "base/macros.h" #include "base/mutex.h" #include "gc_root.h" +#include "handle_scope.h" #include "object_callbacks.h" #include "primitive.h" @@ -205,6 +206,17 @@ class RegType { bool IsAssignableFrom(const RegType& src) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Can this array type potentially be assigned by src. + // This function is necessary as array types are valid even if their components types are not, + // e.g., when they component type could not be resolved. The function will return true iff the + // types are assignable. It will return false otherwise. In case of return=false, soft_error + // will be set to true iff the assignment test failure should be treated as a soft-error, i.e., + // when both array types have the same 'depth' and the 'final' component types may be assignable + // (both are reference types). + bool CanAssignArray(const RegType& src, RegTypeCache& reg_types, + Handle<mirror::ClassLoader> class_loader, bool* soft_error) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Can this type be assigned by src? Variant of IsAssignableFrom that doesn't // allow assignment to // an interface from an Object. |