8178949: The split verifier allows anewarray to create an array of more than 255 dimensions.
authorhseigel
Mon, 24 Apr 2017 08:47:38 -0400
changeset 46403 f2b91b928476
parent 46402 8147e17ad6fa
child 46404 ae62ba99a1a7
child 46405 17ab5460b2cb
8178949: The split verifier allows anewarray to create an array of more than 255 dimensions. Summary: Add check to split verifier handling of anewarray opcode. Reviewed-by: sspitsyn, gtriantafill, lfoltan
hotspot/src/share/vm/classfile/verifier.cpp
hotspot/test/runtime/verifier/TestANewArray.java
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Sun Apr 23 15:02:46 2017 -0400
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Mon Apr 24 08:47:38 2017 -0400
@@ -54,6 +54,7 @@
 #define NOFAILOVER_MAJOR_VERSION                       51
 #define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION  51
 #define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION       52
+#define MAX_ARRAY_DIMENSIONS 255
 
 // Access to external entry for VerifyClassCodes - old byte code verifier
 
@@ -2931,8 +2932,15 @@
   char* arr_sig_str;
   if (component_type.is_array()) {     // it's an array
     const char* component_name = component_type.name()->as_utf8();
+    // Check for more than MAX_ARRAY_DIMENSIONS
+    length = (int)strlen(component_name);
+    if (length > MAX_ARRAY_DIMENSIONS &&
+        component_name[MAX_ARRAY_DIMENSIONS - 1] == '[') {
+      verify_error(ErrorContext::bad_code(bci),
+        "Illegal anewarray instruction, array has more than 255 dimensions");
+    }
     // add one dimension to component
-    length = (int)strlen(component_name) + 1;
+    length++;
     arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length);
     arr_sig_str[0] = '[';
     strncpy(&arr_sig_str[1], component_name, length - 1);
--- a/hotspot/test/runtime/verifier/TestANewArray.java	Sun Apr 23 15:02:46 2017 -0400
+++ b/hotspot/test/runtime/verifier/TestANewArray.java	Mon Apr 24 08:47:38 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,20 +33,17 @@
 
 /*
  * @test
- * @summary Test that anewarray bytecode is valid only if it specifies 255 or fewer dimensions.
+ * @summary Test that anewarray bytecode is valid only if it specifies 254 or fewer dimensions.
+ *          255 is invalid because the anewarray would then create an array with 256 dimensions.
  * @library /test/lib
  * @modules java.base/jdk.internal.org.objectweb.asm
- *          java.base/jdk.internal.misc
- *          java.management
  * @compile -XDignore.symbol.file TestANewArray.java
  * @run main/othervm TestANewArray 49
- * @run main/othervm TestANewArray 50
- * @run main/othervm TestANewArray 51
  * @run main/othervm TestANewArray 52
  */
 
 /*
- * Testing anewarray instruction with 254, 255 & 264 dimensions to verify JVMS 8,
+ * Testing anewarray instruction with 254, 255 & 264 dimensions to verify JVM Spec
  * Section 4.9.1, Static Constraints that states the following:
  *
  * "No anewarray instruction may be used to create an array of more than 255 dimensions."
@@ -83,17 +80,16 @@
         System.err.println("Running with cfv: " + cfv + ", test_Dimension_255");
         pb = ProcessTools.createJavaProcessBuilder(true, "-verify", "-cp", ".",  classCName);
         output = new OutputAnalyzer(pb.start());
+        // If anewarray has an operand with 255 array dimensions then VerifyError should
+        // be thrown because the resulting array would have 256 dimensions.
+        output.shouldContain("java.lang.VerifyError");
+        // VerifyError exception messages differ between verifiers.
         if (cfv == 49) {
-            // The type-inferencing verifier used for <=49.0 ClassFiles detects an anewarray instruction
-            // with exactly 255 dimensions and incorrectly issues the "Array with too many dimensions" VerifyError.
             output.shouldContain("Array with too many dimensions");
-            output.shouldHaveExitValue(1);
         } else {
-            // 255 dimensions should always pass, except for cfv 49
-            output.shouldNotContain("java.lang.VerifyError");
-            output.shouldNotContain("java.lang.ClassFormatError");
-            output.shouldHaveExitValue(0);
+            output.shouldContain("Illegal anewarray instruction, array has more than 255 dimensions");
         }
+        output.shouldHaveExitValue(1);
 
         // 264 array dimensions
         byte[] classFile_264 = dumpClassFile(cfv, test_Dimension_264, array_Dimension_264);