Merge "Fix for interpreter crash on new instance of class"
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 7ecd595..68c954f 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -148,6 +148,11 @@
*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);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f2ae85a..7373819 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -1257,6 +1257,10 @@
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;
}
diff --git a/test/600-verifier-fails/expected.txt b/test/600-verifier-fails/expected.txt
index eaa0c93..974b995 100644
--- a/test/600-verifier-fails/expected.txt
+++ b/test/600-verifier-fails/expected.txt
@@ -3,3 +3,4 @@
passed C
passed D
passed E
+passed F
diff --git a/test/600-verifier-fails/info.txt b/test/600-verifier-fails/info.txt
index df2396e..23f3ebc 100644
--- a/test/600-verifier-fails/info.txt
+++ b/test/600-verifier-fails/info.txt
@@ -17,4 +17,7 @@
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
index 0000000..b2eb254
--- /dev/null
+++ b/test/600-verifier-fails/smali/class.smali
@@ -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
diff --git a/test/600-verifier-fails/src/Main.java b/test/600-verifier-fails/src/Main.java
index fa25d58..1726bc4 100644
--- a/test/600-verifier-fails/src/Main.java
+++ b/test/600-verifier-fails/src/Main.java
@@ -39,5 +39,6 @@
test("C");
test("D");
test("E");
+ test("F");
}
}