diff options
| author | 2016-06-29 14:54:26 -0700 | |
|---|---|---|
| committer | 2016-06-29 14:54:26 -0700 | |
| commit | 2a1b7ac77446d12befceb9946dc418d15119bc05 (patch) | |
| tree | 085d819d474dcb9383908d3b6fd82843a9512516 | |
| parent | 5be510d8feeb3640e3e4f6a257a775194fcb5097 (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.h | 31 | ||||
| -rw-r--r-- | test/600-verifier-fails/expected.txt | 1 | ||||
| -rw-r--r-- | test/600-verifier-fails/src/Main.java | 3 |
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"); } } |