8158297: Lack of proper checking of non-well formed elements in CONSTANT_Utf8_info's structure
Summary: Disallow // in class file names during parsing and throw ClassNotFoundException
Reviewed-by: sspitsyn, rehn, gtriantafill
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Jun 07 18:17:41 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Jun 07 15:34:22 2016 -0400
@@ -4673,6 +4673,7 @@
}
// Unqualified names may not contain the characters '.', ';', '[', or '/'.
+// In class names, '/' separates unqualified names. This is verified in this function also.
// Method names also may not contain the characters '<' or '>', unless <init>
// or <clinit>. Note that method names may not be <init> or <clinit> in this
// method. Because these names have been checked as special cases before
@@ -4698,8 +4699,16 @@
if (ch == ';' || ch == '[' ) {
return false; // do not permit '.', ';', or '['
}
- if (type != ClassFileParser::LegalClass && ch == '/') {
- return false; // do not permit '/' unless it's class name
+ if (ch == '/') {
+ // check for '//' or leading or trailing '/' which are not legal
+ // unqualified name must not be empty
+ if (type == ClassFileParser::LegalClass) {
+ if (p == name || p+1 >= name+length || *(p+1) == '/') {
+ return false;
+ }
+ } else {
+ return false; // do not permit '/' unless it's class name
+ }
}
if (type == ClassFileParser::LegalMethod && (ch == '<' || ch == '>')) {
return false; // do not permit '<' or '>' in method names
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/TestBadClassName.java Tue Jun 07 15:34:22 2016 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8158297
+ * @summary Constant pool utf8 entry for class name cannot have empty qualified name '//'
+ * @compile p1/BadInterface1.jcod
+ * @compile p1/BadInterface2.jcod
+ * @compile UseBadInterface1.jcod
+ * @compile UseBadInterface2.jcod
+ * @run main/othervm -Xverify:all TestBadClassName
+ */
+
+public class TestBadClassName {
+ public static void main(String args[]) throws Throwable {
+
+ System.out.println("Regression test for bug 8042660");
+
+ // Test class name with p1//BadInterface2
+ try {
+ Class newClass = Class.forName("UseBadInterface1");
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ } catch (java.lang.ClassFormatError e) {
+ System.out.println("Test UseBadInterface1 passed test case with illegal class name");
+ }
+
+ // Test class name with p1/BadInterface2/
+ try {
+ Class newClass = Class.forName("UseBadInterface2");
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ } catch (java.lang.ClassFormatError e) {
+ System.out.println("Test UseBadInterface1 passed test case with illegal class name");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/UseBadInterface1.jcod Tue Jun 07 15:34:22 2016 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// jcod file for UseBadInterface1.java
+// class UseBadInterface1 implements p1.BadInterface1 {
+// int i;
+// UseBadInterface1() {}
+// public static void main(java.lang.String[] unused) { }
+// }
+
+class UseBadInterface1 {
+ 0xCAFEBABE;
+ 0; // minor version
+ 53; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #10; // #1
+ Utf8 "UseBadInterface1.java"; // #2
+ class #4; // #3
+ Utf8 "java/lang/Object"; // #4
+ class #8; // #5
+ Utf8 "([Ljava/lang/String;)V"; // #6
+ class #11; // #7
+ Utf8 "UseBadInterface1"; // #8
+ Utf8 "main"; // #9
+ NameAndType #17 #13; // #10
+ Utf8 "p1//BadInterface1"; // #11
+ Utf8 "SourceFile"; // #12
+ Utf8 "()V"; // #13
+ Utf8 "I"; // #14
+ Utf8 "Code"; // #15
+ Utf8 "i"; // #16
+ Utf8 "<init>"; // #17
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ #7;
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #16; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #17; // name_cpx
+ #13; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #9; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 0; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #2;
+ } // end SourceFile
+ } // Attributes
+} // end class UseBadInterface1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/UseBadInterface2.jcod Tue Jun 07 15:34:22 2016 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// jcod file for UseBadInterface2.java
+// class UseBadInterface2 implements p1.BadInterface2 {
+// int i;
+// UseBadInterface2() {}
+// public static void main(java.lang.String[] unused) { }
+// }
+
+class UseBadInterface2 {
+ 0xCAFEBABE;
+ 0; // minor version
+ 53; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #10; // #1
+ Utf8 "UseBadInterface2.java"; // #2
+ class #4; // #3
+ Utf8 "java/lang/Object"; // #4
+ class #8; // #5
+ Utf8 "([Ljava/lang/String;)V"; // #6
+ class #11; // #7
+ Utf8 "UseBadInterface2"; // #8
+ Utf8 "main"; // #9
+ NameAndType #17 #13; // #10
+ Utf8 "p1/BadInterface2/"; // #11
+ Utf8 "SourceFile"; // #12
+ Utf8 "()V"; // #13
+ Utf8 "I"; // #14
+ Utf8 "Code"; // #15
+ Utf8 "i"; // #16
+ Utf8 "<init>"; // #17
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ #7;
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #16; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #17; // name_cpx
+ #13; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #9; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 0; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #2;
+ } // end SourceFile
+ } // Attributes
+} // end class UseBadInterface2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/p1/BadInterface1.jcod Tue Jun 07 15:34:22 2016 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// Interface that should get a ClassFormatException for the "//" in the name
+
+// package p1;
+// public interface cls1 {}
+
+class p1//BadInterface1 {
+ 0xCAFEBABE;
+ 0; // minor version
+ 53; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ class #5; // #1
+ class #6; // #2
+ Utf8 "SourceFile"; // #3
+ Utf8 "BadInterface1.java"; // #4
+ Utf8 "p1//BadInterface1"; // #5
+ Utf8 "java/lang/Object"; // #6
+ } // Constant Pool
+
+ 0x0601; // access
+ #1;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ } // methods
+
+ [] { // Attributes
+ Attr(#3) { // SourceFile
+ #4;
+ } // end SourceFile
+ } // Attributes
+} // end class p1//BadInterface1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/p1/BadInterface2.jcod Tue Jun 07 15:34:22 2016 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// Interface that should get a ClassFormatException for the trailing "/" in the name
+
+// package p1;
+// public interface cls1 {}
+
+class p1/BadInterface2/ {
+ 0xCAFEBABE;
+ 0; // minor version
+ 53; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ class #5; // #1
+ class #6; // #2
+ Utf8 "SourceFile"; // #3
+ Utf8 "BadInterface2.java"; // #4
+ Utf8 "p1/BadInterface2/"; // #5
+ Utf8 "java/lang/Object"; // #6
+ } // Constant Pool
+
+ 0x0601; // access
+ #1;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ } // methods
+
+ [] { // Attributes
+ Attr(#3) { // SourceFile
+ #4;
+ } // end SourceFile
+ } // Attributes
+} // end class p1/BadInterface2