diff options
author | 2020-10-20 15:17:53 +0100 | |
---|---|---|
committer | 2020-10-21 13:23:28 +0000 | |
commit | 5b041c05d6b73b73c43a425dc4ff3b784722c4a2 (patch) | |
tree | 0425b87cf343b8a45182c053d7e300623b64d419 | |
parent | 8bea400eec977e433ad3453c5a21f74955afbc2a (diff) |
Remove unassignable_types from vdex.
These were used in case a class went from "verified-at-runtime" to
"verified". With go/nterp, we're re not going to handle this situation
and we should only record what types the verifier expects to be
assignable.
Test: test.py
Bug: 112676029
Change-Id: I6ffa61cef3aa767dfccadbdfdd5432e72e143ca3
-rw-r--r-- | compiler/dex/verified_method.cc | 4 | ||||
-rw-r--r-- | dex2oat/verifier_deps_test.cc | 163 | ||||
-rw-r--r-- | runtime/vdex_file.h | 4 | ||||
-rw-r--r-- | runtime/verifier/reg_type-inl.h | 4 | ||||
-rw-r--r-- | runtime/verifier/reg_type.cc | 8 | ||||
-rw-r--r-- | runtime/verifier/verifier_deps.cc | 56 | ||||
-rw-r--r-- | runtime/verifier/verifier_deps.h | 9 |
7 files changed, 56 insertions, 192 deletions
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc index 172ec6b102..d7dc310230 100644 --- a/compiler/dex/verified_method.cc +++ b/compiler/dex/verified_method.cc @@ -92,9 +92,7 @@ void VerifiedMethod::GenerateSafeCastSet(verifier::MethodVerifier* method_verifi DCHECK(cast_type.HasClass()); verifier::VerifierDeps::MaybeRecordAssignability(method_verifier->GetDexFile(), cast_type.GetClass(), - reg_type.GetClass(), - /* is_strict= */ true, - /* is_assignable= */ true); + reg_type.GetClass()); } if (safe_cast_set_ == nullptr) { safe_cast_set_.reset(new SafeCastSet()); diff --git a/dex2oat/verifier_deps_test.cc b/dex2oat/verifier_deps_test.cc index 0e0ce91025..c95a53e711 100644 --- a/dex2oat/verifier_deps_test.cc +++ b/dex2oat/verifier_deps_test.cc @@ -199,10 +199,7 @@ class VerifierDepsTest : public CommonCompilerDriverTest { VerifyWithCompilerDriver(/* verifier_deps= */ nullptr); } - bool TestAssignabilityRecording(const std::string& dst, - const std::string& src, - bool is_strict, - bool is_assignable) { + bool TestAssignabilityRecording(const std::string& dst, const std::string& src) { ScopedObjectAccess soa(Thread::Current()); LoadDexFile(soa); StackHandleScope<1> hs(soa.Self()); @@ -212,9 +209,7 @@ class VerifierDepsTest : public CommonCompilerDriverTest { DCHECK(klass_src != nullptr) << src; verifier_deps_->AddAssignability(*primary_dex_file_, klass_dst.Get(), - klass_src, - is_strict, - is_assignable); + klass_src); return true; } @@ -273,12 +268,10 @@ class VerifierDepsTest : public CommonCompilerDriverTest { // Iterates over all assignability records and tries to find an entry which // matches the expected destination/source pair. bool HasAssignable(const std::string& expected_destination, - const std::string& expected_source, - bool expected_is_assignable) { + const std::string& expected_source) { for (auto& dex_dep : verifier_deps_->dex_deps_) { const DexFile& dex_file = *dex_dep.first; - auto& storage = expected_is_assignable ? dex_dep.second->assignable_types_ - : dex_dep.second->unassignable_types_; + auto& storage = dex_dep.second->assignable_types_; for (auto& entry : storage) { std::string actual_destination = verifier_deps_->GetStringFromId(dex_file, entry.GetDestination()); @@ -310,7 +303,6 @@ class VerifierDepsTest : public CommonCompilerDriverTest { for (auto& entry : verifier_deps_->dex_deps_) { has_strings |= !entry.second->strings_.empty(); has_assignability |= !entry.second->assignable_types_.empty(); - has_assignability |= !entry.second->unassignable_types_.empty(); has_verified_classes |= HasBoolValue(entry.second->verified_classes_, true); has_unverified_classes |= HasBoolValue(entry.second->verified_classes_, false); has_redefined_classes |= HasBoolValue(entry.second->redefined_classes_, true); @@ -387,178 +379,125 @@ TEST_F(VerifierDepsTest, StringToId) { TEST_F(VerifierDepsTest, Assignable_BothInBoot) { ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/util/TimeZone;", - /* src= */ "Ljava/util/SimpleTimeZone;", - /* is_strict= */ true, - /* is_assignable= */ true)); - ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true)); + /* src= */ "Ljava/util/SimpleTimeZone;")); + ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;")); } TEST_F(VerifierDepsTest, Assignable_DestinationInBoot1) { ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/net/Socket;", - /* src= */ "LMySSLSocket;", - /* is_strict= */ true, - /* is_assignable= */ true)); - ASSERT_TRUE(HasAssignable("Ljava/net/Socket;", "Ljavax/net/ssl/SSLSocket;", true)); + /* src= */ "LMySSLSocket;")); + ASSERT_TRUE(HasAssignable("Ljava/net/Socket;", "Ljavax/net/ssl/SSLSocket;")); } TEST_F(VerifierDepsTest, Assignable_DestinationInBoot2) { ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/util/TimeZone;", - /* src= */ "LMySimpleTimeZone;", - /* is_strict= */ true, - /* is_assignable= */ true)); - ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true)); + /* src= */ "LMySimpleTimeZone;")); + ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;")); } TEST_F(VerifierDepsTest, Assignable_DestinationInBoot3) { ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/util/Collection;", - /* src= */ "LMyThreadSet;", - /* is_strict= */ true, - /* is_assignable= */ true)); - ASSERT_TRUE(HasAssignable("Ljava/util/Collection;", "Ljava/util/Set;", true)); + /* src= */ "LMyThreadSet;")); + ASSERT_TRUE(HasAssignable("Ljava/util/Collection;", "Ljava/util/Set;")); } TEST_F(VerifierDepsTest, Assignable_BothArrays_Resolved) { ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "[[Ljava/util/TimeZone;", - /* src= */ "[[Ljava/util/SimpleTimeZone;", - /* is_strict= */ true, - /* is_assignable= */ true)); + /* src= */ "[[Ljava/util/SimpleTimeZone;")); // If the component types of both arrays are resolved, we optimize the list of // dependencies by recording a dependency on the component types. - ASSERT_FALSE(HasAssignable("[[Ljava/util/TimeZone;", "[[Ljava/util/SimpleTimeZone;", true)); - ASSERT_FALSE(HasAssignable("[Ljava/util/TimeZone;", "[Ljava/util/SimpleTimeZone;", true)); - ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true)); -} - -TEST_F(VerifierDepsTest, NotAssignable_BothInBoot) { - ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;", - /* src= */ "Ljava/util/SimpleTimeZone;", - /* is_strict= */ true, - /* is_assignable= */ false)); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/util/SimpleTimeZone;", false)); -} - -TEST_F(VerifierDepsTest, NotAssignable_DestinationInBoot1) { - ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;", - /* src= */ "LMySSLSocket;", - /* is_strict= */ true, - /* is_assignable= */ false)); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljavax/net/ssl/SSLSocket;", false)); -} - -TEST_F(VerifierDepsTest, NotAssignable_DestinationInBoot2) { - ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;", - /* src= */ "LMySimpleTimeZone;", - /* is_strict= */ true, - /* is_assignable= */ false)); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/util/SimpleTimeZone;", false)); -} - -TEST_F(VerifierDepsTest, NotAssignable_BothArrays) { - ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "[Ljava/lang/Exception;", - /* src= */ "[Ljava/util/SimpleTimeZone;", - /* is_strict= */ true, - /* is_assignable= */ false)); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/util/SimpleTimeZone;", false)); + ASSERT_FALSE(HasAssignable("[[Ljava/util/TimeZone;", "[[Ljava/util/SimpleTimeZone;")); + ASSERT_FALSE(HasAssignable("[Ljava/util/TimeZone;", "[Ljava/util/SimpleTimeZone;")); + ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;")); } TEST_F(VerifierDepsTest, ReturnType_Reference) { ASSERT_TRUE(VerifyMethod("ReturnType_Reference")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;", true)); -} - -TEST_F(VerifierDepsTest, ReturnType_Array) { - ASSERT_FALSE(VerifyMethod("ReturnType_Array")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Integer;", "Ljava/lang/IllegalStateException;", false)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;")); } TEST_F(VerifierDepsTest, InvokeArgumentType) { ASSERT_TRUE(VerifyMethod("InvokeArgumentType")); - ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;", true)); + ASSERT_TRUE(HasAssignable("Ljava/util/TimeZone;", "Ljava/util/SimpleTimeZone;")); } TEST_F(VerifierDepsTest, MergeTypes_RegisterLines) { ASSERT_TRUE(VerifyMethod("MergeTypes_RegisterLines")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;")); ASSERT_TRUE(HasAssignable( - "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;", true)); + "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;")); } TEST_F(VerifierDepsTest, MergeTypes_IfInstanceOf) { ASSERT_TRUE(VerifyMethod("MergeTypes_IfInstanceOf")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;")); ASSERT_TRUE(HasAssignable( - "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;", true)); - ASSERT_TRUE(HasAssignable("Ljava/net/SocketTimeoutException;", "Ljava/lang/Exception;", false)); + "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;")); } TEST_F(VerifierDepsTest, MergeTypes_Unresolved) { ASSERT_TRUE(VerifyMethod("MergeTypes_Unresolved")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "Ljava/net/SocketTimeoutException;")); ASSERT_TRUE(HasAssignable( - "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;", true)); + "Ljava/lang/Exception;", "Ljava/util/concurrent/TimeoutException;")); } TEST_F(VerifierDepsTest, Throw) { ASSERT_TRUE(VerifyMethod("Throw")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/lang/IllegalStateException;")); } TEST_F(VerifierDepsTest, MoveException_Resolved) { ASSERT_TRUE(VerifyMethod("MoveException_Resolved")); // Testing that all exception types are assignable to Throwable. - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/InterruptedIOException;", true)); - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;", true)); - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/util/zip/ZipException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/InterruptedIOException;")); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;")); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/util/zip/ZipException;")); // Testing that the merge type is assignable to Throwable. - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/IOException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/io/IOException;")); // Merging of exception types. - ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/io/InterruptedIOException;", true)); - ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/util/zip/ZipException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/io/InterruptedIOException;")); + ASSERT_TRUE(HasAssignable("Ljava/io/IOException;", "Ljava/util/zip/ZipException;")); ASSERT_TRUE(HasAssignable( - "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true)); + "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;")); } TEST_F(VerifierDepsTest, InstanceField_Resolved_DeclaredInReferenced) { ASSERT_TRUE(VerifyMethod("InstanceField_Resolved_DeclaredInReferenced")); ASSERT_TRUE(HasAssignable( - "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true)); + "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;")); } TEST_F(VerifierDepsTest, InstanceField_Resolved_DeclaredInSuperclass1) { ASSERT_TRUE(VerifyMethod("InstanceField_Resolved_DeclaredInSuperclass1")); ASSERT_TRUE(HasAssignable( - "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true)); + "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;")); } TEST_F(VerifierDepsTest, InstanceField_Resolved_DeclaredInSuperclass2) { ASSERT_TRUE(VerifyMethod("InstanceField_Resolved_DeclaredInSuperclass2")); ASSERT_TRUE(HasAssignable( - "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;", true)); + "Ljava/io/InterruptedIOException;", "Ljava/net/SocketTimeoutException;")); } TEST_F(VerifierDepsTest, InvokeVirtual_Resolved_DeclaredInReferenced) { ASSERT_TRUE(VerifyMethod("InvokeVirtual_Resolved_DeclaredInReferenced")); // Type dependency on `this` argument. - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;")); } TEST_F(VerifierDepsTest, InvokeVirtual_Resolved_DeclaredInSuperclass1) { ASSERT_TRUE(VerifyMethod("InvokeVirtual_Resolved_DeclaredInSuperclass1")); // Type dependency on `this` argument. - ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;", true)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Throwable;", "Ljava/net/SocketTimeoutException;")); } TEST_F(VerifierDepsTest, InvokeSuper_ThisAssignable) { ASSERT_TRUE(VerifyMethod("InvokeSuper_ThisAssignable")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Runnable;", "Ljava/lang/Thread;", true)); -} - -TEST_F(VerifierDepsTest, InvokeSuper_ThisNotAssignable) { - ASSERT_FALSE(VerifyMethod("InvokeSuper_ThisNotAssignable")); - ASSERT_TRUE(HasAssignable("Ljava/lang/Integer;", "Ljava/lang/Thread;", false)); + ASSERT_TRUE(HasAssignable("Ljava/lang/Runnable;", "Ljava/lang/Thread;")); } TEST_F(VerifierDepsTest, EncodeDecode) { @@ -677,16 +616,6 @@ TEST_F(VerifierDepsTest, VerifyDeps) { // Check that dependencies are satisfied after decoding `buffer`. ASSERT_TRUE(RunValidation([](VerifierDeps::DexFileDeps&) {}, buffer, &error_msg)) << error_msg; - - // Mess with the dependencies to make sure we catch any change and fail to verify. - ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) { - deps.assignable_types_.insert(*deps.unassignable_types_.begin()); - }, buffer, &error_msg)); - - // Mess with the unassignable_types. - ASSERT_FALSE(RunValidation([](VerifierDeps::DexFileDeps& deps) { - deps.unassignable_types_.insert(*deps.assignable_types_.begin()); - }, buffer, &error_msg)); } TEST_F(VerifierDepsTest, CompilerDriver) { @@ -738,23 +667,11 @@ TEST_F(VerifierDepsTest, MultiDexVerification) { ASSERT_FALSE(buffer.empty()); } -TEST_F(VerifierDepsTest, NotAssignable_InterfaceWithClassInBoot) { - ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "Ljava/lang/Exception;", - /* src= */ "LIface;", - /* is_strict= */ true, - /* is_assignable= */ false)); - ASSERT_TRUE(HasAssignable("Ljava/lang/Exception;", "LIface;", false)); -} - TEST_F(VerifierDepsTest, Assignable_Arrays) { ASSERT_TRUE(TestAssignabilityRecording(/* dst= */ "[LIface;", - /* src= */ "[LMyClassExtendingInterface;", - /* is_strict= */ false, - /* is_assignable= */ true)); - ASSERT_FALSE(HasAssignable( - "LIface;", "LMyClassExtendingInterface;", /* expected_is_assignable= */ true)); + /* src= */ "[LMyClassExtendingInterface;")); ASSERT_FALSE(HasAssignable( - "LIface;", "LMyClassExtendingInterface;", /* expected_is_assignable= */ false)); + "LIface;", "LMyClassExtendingInterface;")); } } // namespace verifier diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h index 98efaa1511..a9532354a2 100644 --- a/runtime/vdex_file.h +++ b/runtime/vdex_file.h @@ -114,8 +114,8 @@ class VdexFile { static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' }; // The format version of the verifier deps header and the verifier deps. - // Last update: Remove class/field/method resolution. - static constexpr uint8_t kVerifierDepsVersion[] = { '0', '2', '2', '\0' }; + // Last update: Remove unassignable types. + static constexpr uint8_t kVerifierDepsVersion[] = { '0', '2', '3', '\0' }; // The format version of the dex section header and the dex section, containing // both the dex code and the quickening data. diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h index 9e12d636d4..3c7ad03ceb 100644 --- a/runtime/verifier/reg_type-inl.h +++ b/runtime/verifier/reg_type-inl.h @@ -115,9 +115,9 @@ inline bool RegType::AssignableFrom(const RegType& lhs, bool result = lhs.GetClass()->IsAssignableFrom(rhs.GetClass()); // Record assignability dependency. The `verifier` is null during unit tests and // VerifiedMethod::GenerateSafeCastSet. - if (verifier != nullptr) { + if (verifier != nullptr && result) { VerifierDeps::MaybeRecordAssignability( - verifier->GetDexFile(), lhs.GetClass(), rhs.GetClass(), strict, result); + verifier->GetDexFile(), lhs.GetClass(), rhs.GetClass()); } return result; } else { diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 2d170307a2..c313e90839 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -903,14 +903,10 @@ const RegType& RegType::Merge(const RegType& incoming_type, if (verifier != nullptr) { VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(), join_class, - GetClass(), - /* is_strict= */ true, - /* is_assignable= */ true); + GetClass()); VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(), join_class, - incoming_type.GetClass(), - /* is_strict= */ true, - /* is_assignable= */ true); + incoming_type.GetClass()); } if (GetClass() == join_class && !IsPreciseReference()) { return *this; diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index dd68416b55..1df5c02215 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -68,7 +68,6 @@ void VerifierDeps::MergeWith(std::unique_ptr<VerifierDeps> other, // which should be the one passed as `this` in this method. DCHECK(other_deps.strings_.empty()); my_deps->assignable_types_.merge(other_deps.assignable_types_); - my_deps->unassignable_types_.merge(other_deps.unassignable_types_); BitVectorOr(my_deps->verified_classes_, other_deps.verified_classes_); BitVectorOr(my_deps->redefined_classes_, other_deps.redefined_classes_); } @@ -272,9 +271,7 @@ ObjPtr<mirror::Class> VerifierDeps::FindOneClassPathBoundaryForInterface( void VerifierDeps::AddAssignability(const DexFile& dex_file, ObjPtr<mirror::Class> destination, - ObjPtr<mirror::Class> source, - bool is_strict, - bool is_assignable) { + ObjPtr<mirror::Class> source) { // Test that the method is only called on reference types. // Note that concurrent verification of `destination` and `source` may have // set their status to erroneous. However, the tests performed below rely @@ -291,17 +288,8 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file, return; } - if (source->IsObjectClass() && !is_assignable) { - // j.l.Object is trivially non-assignable to other types, don't - // record it. - return; - } - - if (destination == source || - destination->IsObjectClass() || - (!is_strict && destination->IsInterface())) { + if (destination == source || destination->IsObjectClass()) { // Cases when `destination` is trivially assignable from `source`. - DCHECK(is_assignable); return; } @@ -317,15 +305,9 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file, if (destination_component->IsResolved() && source_component->IsResolved()) { AddAssignability(dex_file, destination_component, - source_component, - /* is_strict= */ true, - is_assignable); + source_component); return; } - } else { - // We only do this check for non-array types, as arrays might have erroneous - // component types which makes the IsAssignableFrom check unreliable. - DCHECK_EQ(is_assignable, destination->IsAssignableFrom(source)); } DexFileDeps* dex_deps = GetDexFileDeps(dex_file); @@ -352,7 +334,7 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file, if (source == destination) { return; } - } else if (is_assignable) { + } else { source = FindOneClassPathBoundaryForInterface(destination, source); if (source == nullptr) { // There was no classpath boundary, no need to record. @@ -367,11 +349,7 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file, dex::StringIndex destination_id = GetClassDescriptorStringId(dex_file, destination); dex::StringIndex source_id = GetClassDescriptorStringId(dex_file, source); - if (is_assignable) { - dex_deps->assignable_types_.emplace(TypeAssignability(destination_id, source_id)); - } else { - dex_deps->unassignable_types_.emplace(TypeAssignability(destination_id, source_id)); - } + dex_deps->assignable_types_.emplace(TypeAssignability(destination_id, source_id)); } void VerifierDeps::MaybeRecordClassRedefinition(const DexFile& dex_file, @@ -405,12 +383,10 @@ void VerifierDeps::RecordClassVerified(const DexFile& dex_file, const dex::Class void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file, ObjPtr<mirror::Class> destination, - ObjPtr<mirror::Class> source, - bool is_strict, - bool is_assignable) { + ObjPtr<mirror::Class> source) { VerifierDeps* thread_deps = GetThreadLocalVerifierDeps(); if (thread_deps != nullptr) { - thread_deps->AddAssignability(dex_file, destination, source, is_strict, is_assignable); + thread_deps->AddAssignability(dex_file, destination, source); } } @@ -579,7 +555,6 @@ void VerifierDeps::Encode(const std::vector<const DexFile*>& dex_files, const DexFileDeps& deps = *GetDexFileDeps(*dex_file); EncodeStringVector(buffer, deps.strings_); EncodeSet(buffer, deps.assignable_types_); - EncodeSet(buffer, deps.unassignable_types_); EncodeUint16SparseBitVector(buffer, deps.verified_classes_, /* sparse_value= */ false); EncodeUint16SparseBitVector(buffer, deps.redefined_classes_, /* sparse_value= */ true); } @@ -595,8 +570,6 @@ bool VerifierDeps::DecodeDexFileDeps(DexFileDeps& deps, data_start, data_end, &deps.strings_) && DecodeSet</*kFillSet=*/ !kOnlyVerifiedClasses>( data_start, data_end, &deps.assignable_types_) && - DecodeSet</*kFillSet=*/ !kOnlyVerifiedClasses>( - data_start, data_end, &deps.unassignable_types_) && DecodeUint16SparseBitVector</*kFillVector=*/ true>( data_start, data_end, num_class_defs, /*sparse_value=*/ false, &deps.verified_classes_) && DecodeUint16SparseBitVector</*kFillVector=*/ !kOnlyVerifiedClasses>( @@ -686,7 +659,6 @@ bool VerifierDeps::Equals(const VerifierDeps& rhs) const { bool VerifierDeps::DexFileDeps::Equals(const VerifierDeps::DexFileDeps& rhs) const { return (strings_ == rhs.strings_) && (assignable_types_ == rhs.assignable_types_) && - (unassignable_types_ == rhs.unassignable_types_) && (verified_classes_ == rhs.verified_classes_); } @@ -725,14 +697,6 @@ void VerifierDeps::Dump(VariableIndentationOutputStream* vios) const { << "\n"; } - for (const TypeAssignability& entry : dep.second->unassignable_types_) { - vios->Stream() - << GetStringFromId(dex_file, entry.GetSource()) - << " must not be assignable to " - << GetStringFromId(dex_file, entry.GetDestination()) - << "\n"; - } - for (size_t idx = 0; idx < dep.second->verified_classes_.size(); idx++) { if (!dep.second->verified_classes_[idx]) { vios->Stream() @@ -878,12 +842,6 @@ bool VerifierDeps::VerifyDexFile(Handle<mirror::ClassLoader> class_loader, deps.assignable_types_, /* expected_assignability= */ true, self, - error_msg) && - VerifyAssignability(class_loader, - dex_file, - deps.unassignable_types_, - /* expected_assignability= */ false, - self, error_msg); } diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index 15fb4a51d9..b11ccb687f 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -89,9 +89,7 @@ class VerifierDeps { // owner of the method for which MethodVerifier performed the assignability test. static void MaybeRecordAssignability(const DexFile& dex_file, ObjPtr<mirror::Class> destination, - ObjPtr<mirror::Class> source, - bool is_strict, - bool is_assignable) + ObjPtr<mirror::Class> source) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::verifier_deps_lock_); @@ -155,7 +153,6 @@ class VerifierDeps { // Set of class pairs recording the outcome of assignability test from one // of the two types to the other. std::set<TypeAssignability> assignable_types_; - std::set<TypeAssignability> unassignable_types_; // Bit vector indexed by class def indices indicating whether the corresponding // class was successfully verified. @@ -213,9 +210,7 @@ class VerifierDeps { void AddAssignability(const DexFile& dex_file, ObjPtr<mirror::Class> destination, - ObjPtr<mirror::Class> source, - bool is_strict, - bool is_assignable) + ObjPtr<mirror::Class> source) REQUIRES_SHARED(Locks::mutator_lock_); bool Equals(const VerifierDeps& rhs) const; |