OSDN Git Service

Fix for interpreter crash on new instance of class
authorAart Bik <ajcbik@google.com>
Tue, 26 Jul 2016 00:52:22 +0000 (17:52 -0700)
committerAart Bik <ajcbik@google.com>
Fri, 29 Jul 2016 22:53:18 +0000 (15:53 -0700)
Rationale:
Fuzz testing found divergences between the compiler and interpreter
which turned out to be caused by calling instance on java.lang.Class
(this worked for compiler but crashed interpeter). Since RI does not
allow this construct, solution is to force interpreter in this
unlikely case and throw run time exception like RI. This fixes
two cases found with fuzz testing. CL also includes
fail-before/pass-after test.

Test: 600-verifier-fails

BUG=29758098

Change-Id: Ie80f7758def44e6655d28fec4c10c34ffa0fd60b

runtime/entrypoints/entrypoint_utils-inl.h
runtime/verifier/method_verifier.cc
test/600-verifier-fails/expected.txt
test/600-verifier-fails/info.txt
test/600-verifier-fails/smali/class.smali [new file with mode: 0644]
test/600-verifier-fails/src/Main.java

index 7ecd595..68c954f 100644 (file)
@@ -148,6 +148,11 @@ inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
       *slow_path = true;
       return nullptr;  // Failure
     }
+    if (UNLIKELY(klass->IsClassClass())) {
+      ThrowIllegalAccessError(nullptr, "Class %s is inaccessible", PrettyDescriptor(klass).c_str());
+      *slow_path = true;
+      return nullptr;  // Failure
+    }
     mirror::Class* referrer = method->GetDeclaringClass();
     if (UNLIKELY(!referrer->CanAccess(klass))) {
       ThrowIllegalAccessErrorClass(referrer, klass);
index f2ae85a..7373819 100644 (file)
@@ -1257,6 +1257,10 @@ inline bool MethodVerifier::CheckNewInstance(uint32_t idx) {
   if (descriptor[0] != 'L') {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "can't call new-instance on type '" << descriptor << "'";
     return false;
+  } else if (strcmp(descriptor, "Ljava/lang/Class;") == 0) {
+    // An unlikely new instance on Class is not allowed. Fall back to interpreter to ensure an
+    // exception is thrown when this statement is executed (compiled code would not do that).
+    Fail(VERIFY_ERROR_INSTANTIATION);
   }
   return true;
 }
index eaa0c93..974b995 100644 (file)
@@ -3,3 +3,4 @@ passed B
 passed C
 passed D
 passed E
+passed F
index df2396e..23f3ebc 100644 (file)
@@ -17,4 +17,7 @@ dexfuzz on the DEX files of fuzzingly random generated Java test.
     later on
 (E) b/29068831:
     access validation on method should occur prior to null reference check
+(F) b/29758098:
+    new-instance of java.lang.Class should throw an IllegalAccessError to
+    avoid interpreter crash on zero size object later
 
diff --git a/test/600-verifier-fails/smali/class.smali b/test/600-verifier-fails/smali/class.smali
new file mode 100644 (file)
index 0000000..b2eb254
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LF;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+.registers 2
+    invoke-direct {v1}, Ljava/lang/Object;-><init>()V
+    new-instance v0, Ljava/lang/Class;
+    return-void
+.end method
index fa25d58..1726bc4 100644 (file)
@@ -39,5 +39,6 @@ public class Main {
     test("C");
     test("D");
     test("E");
+    test("F");
   }
 }