summaryrefslogtreecommitdiffstats
path: root/runtime/verifier
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-06-22 11:35:46 -0700
committerAndreas Gampe <agampe@google.com>2015-06-22 14:15:12 -0700
commit4c67a6aae0eba853e84090dfb06daefe43d3dc95 (patch)
tree5bb5e26880bbc6fd047b993ae35107f393027075 /runtime/verifier
parent421e495c9bc53649605639dd738b8da8669147f1 (diff)
downloadart-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
Diffstat (limited to 'runtime/verifier')
-rw-r--r--runtime/verifier/method_verifier.cc32
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()) {