diff options
author | Andreas Gampe <agampe@google.com> | 2015-06-22 11:35:46 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-06-22 14:15:12 -0700 |
commit | 4c67a6aae0eba853e84090dfb06daefe43d3dc95 (patch) | |
tree | 5bb5e26880bbc6fd047b993ae35107f393027075 | |
parent | 421e495c9bc53649605639dd738b8da8669147f1 (diff) | |
download | art-4c67a6aae0eba853e84090dfb06daefe43d3dc95.zip art-4c67a6aae0eba853e84090dfb06daefe43d3dc95.tar.gz art-4c67a6aae0eba853e84090dfb06daefe43d3dc95.tar.bz2 |
ART: Allow checking RETURN_VOID_NO_BARRIER on unresolved classes
We must check that all fields are non-final, even for unresolved
classes. Fall back to the dex file for this information.
Bug: 22005084
Bug: https://code.google.com/p/android/issues/detail?id=177694
(cherry picked from commit 68df32091cc79468c81956633e279523b48ea8bf)
Change-Id: If2126d1be5dccadbbedcdccabde7398688d6e5ca
-rw-r--r-- | runtime/verifier/method_verifier.cc | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index fe14d13..6c55356 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -1561,6 +1561,27 @@ bool MethodVerifier::CodeFlowVerifyMethod() { return true; } +// Returns the index of the first final instance field of the given class, or kDexNoIndex if there +// is no such field. +static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, uint16_t type_idx) { + const DexFile::ClassDef* class_def = dex_file.FindClassDef(type_idx); + DCHECK(class_def != nullptr); + const uint8_t* class_data = dex_file.GetClassData(*class_def); + DCHECK(class_data != nullptr); + ClassDataItemIterator it(dex_file, class_data); + // Skip static fields. + while (it.HasNextStaticField()) { + it.Next(); + } + while (it.HasNextInstanceField()) { + if ((it.GetFieldAccessFlags() & kAccFinal) != 0) { + return it.GetMemberIndex(); + } + it.Next(); + } + return DexFile::kDexNoIndex; +} + bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { // If we're doing FindLocksAtDexPc, check whether we're at the dex pc we care about. // We want the state _before_ the instruction, for the case where the dex pc we're @@ -2784,6 +2805,17 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { case Instruction::RETURN_VOID_NO_BARRIER: if (IsConstructor() && !IsStatic()) { auto& declaring_class = GetDeclaringClass(); + if (declaring_class.IsUnresolvedReference()) { + // We must iterate over the fields, even if we cannot use mirror classes to do so. Do it + // manually over the underlying dex file. + uint32_t first_index = GetFirstFinalInstanceFieldIndex(*dex_file_, + dex_file_->GetMethodId(dex_method_idx_).class_idx_); + if (first_index != DexFile::kDexNoIndex) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-no-barrier not expected for field " + << first_index; + } + break; + } auto* klass = declaring_class.GetClass(); for (uint32_t i = 0, num_fields = klass->NumInstanceFields(); i < num_fields; ++i) { if (klass->GetInstanceField(i)->IsFinal()) { |