summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Aart Bik <ajcbik@google.com> 2016-06-29 14:54:26 -0700
committer Aart Bik <ajcbik@google.com> 2016-06-29 14:54:26 -0700
commit2a1b7ac77446d12befceb9946dc418d15119bc05 (patch)
tree085d819d474dcb9383908d3b6fd82843a9512516
parent5be510d8feeb3640e3e4f6a257a775194fcb5097 (diff)
Fix divergence between interpreter and compiler.
Rationale: Access checks on a method invocation should be performed prior to checking null pointer for non-static method calls. Test: 600-verifier-fails BUG=29068831 Change-Id: I21874d96ff83e7e6c6cf7c239e65ce1b515b9729
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h31
-rw-r--r--test/600-verifier-fails/expected.txt1
-rw-r--r--test/600-verifier-fails/src/Main.java3
3 files changed, 19 insertions, 16 deletions
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index fc6257302a..1b55d2f331 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -448,23 +448,10 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object** this_
: ClassLinker::kNoICCECheckForCache;
resolved_method = class_linker->ResolveMethod<resolve_mode>(self, method_idx, referrer, type);
}
+ // Resolution and access check.
if (UNLIKELY(resolved_method == nullptr)) {
DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
return nullptr; // Failure.
- } else if (UNLIKELY(*this_object == nullptr && type != kStatic)) {
- if (UNLIKELY(resolved_method->GetDeclaringClass()->IsStringClass() &&
- resolved_method->IsConstructor())) {
- // Hack for String init:
- //
- // We assume that the input of String.<init> in verified code is always
- // an unitialized reference. If it is a null constant, it must have been
- // optimized out by the compiler. Do not throw NullPointerException.
- } else {
- // Maintain interpreter-like semantics where NullPointerException is thrown
- // after potential NoSuchMethodError from class linker.
- ThrowNullPointerExceptionForMethodAccess(method_idx, type);
- return nullptr; // Failure.
- }
} else if (access_check) {
mirror::Class* methods_class = resolved_method->GetDeclaringClass();
bool can_access_resolved_method =
@@ -482,6 +469,22 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object** this_
return nullptr; // Failure.
}
}
+ // Next, null pointer check.
+ if (UNLIKELY(*this_object == nullptr && type != kStatic)) {
+ if (UNLIKELY(resolved_method->GetDeclaringClass()->IsStringClass() &&
+ resolved_method->IsConstructor())) {
+ // Hack for String init:
+ //
+ // We assume that the input of String.<init> in verified code is always
+ // an unitialized reference. If it is a null constant, it must have been
+ // optimized out by the compiler. Do not throw NullPointerException.
+ } else {
+ // Maintain interpreter-like semantics where NullPointerException is thrown
+ // after potential NoSuchMethodError from class linker.
+ ThrowNullPointerExceptionForMethodAccess(method_idx, type);
+ return nullptr; // Failure.
+ }
+ }
switch (type) {
case kStatic:
case kDirect:
diff --git a/test/600-verifier-fails/expected.txt b/test/600-verifier-fails/expected.txt
index 8399969a2d..eaa0c933c4 100644
--- a/test/600-verifier-fails/expected.txt
+++ b/test/600-verifier-fails/expected.txt
@@ -2,3 +2,4 @@ passed A
passed B
passed C
passed D
+passed E
diff --git a/test/600-verifier-fails/src/Main.java b/test/600-verifier-fails/src/Main.java
index 64c3d5c16a..fa25d58e43 100644
--- a/test/600-verifier-fails/src/Main.java
+++ b/test/600-verifier-fails/src/Main.java
@@ -38,7 +38,6 @@ public class Main {
test("B");
test("C");
test("D");
- // TODO: enable again
- // test("E");
+ test("E");
}
}