# HG changeset patch # User hseigel # Date 1447162973 18000 # Node ID 77ebbd9b0ecc81f9f9bb4a8671e69b08784cee0a # Parent 8745ee8ac1db2f1a264ca9f4f569562879226025 8139164: JVM should throw ClassFormatError for non-void methods named Summary: If method being parsed is named , throw ClassFormatError if it is not void or has arguments, for class file version >= 51. Reviewed-by: acorn, lfoltan diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Nov 10 04:37:35 2015 +0000 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Nov 10 08:42:53 2015 -0500 @@ -92,6 +92,7 @@ // Used for backward compatibility reasons: // - to check NameAndType_info signatures more aggressively +// - to disallow argument and require ACC_STATIC for methods #define JAVA_7_VERSION 51 // Extension method support. @@ -1997,9 +1998,7 @@ } else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) { flags &= JVM_ACC_STATIC | JVM_ACC_STRICT; } else { - // As of major_version 51, a method named without ACC_STATIC is - // just another method. So, do a normal method modifer check. - verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle)); + classfile_parse_error("Method is not static in class file %s", CHECK_(nullHandle)); } } else { verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle)); @@ -5159,6 +5158,14 @@ return -2; } + // Class initializers cannot have args for class format version >= 51. + if (name == vmSymbols::class_initializer_name() && + signature != vmSymbols::void_method_signature() && + _major_version >= JAVA_7_VERSION) { + throwIllegalSignature("Method", name, signature, CHECK_0); + return 0; + } + unsigned int args_size = 0; char buf[fixed_buffer_size]; char* p = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); @@ -5182,8 +5189,8 @@ // The first non-signature thing better be a ')' if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) { length--; - if (name == vmSymbols::object_initializer_name()) { - // All "" methods must return void + if (name->utf8_length() > 0 && name->byte_at(0) == '<') { + // All internal methods must return void if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) { return args_size; } diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/src/share/vm/classfile/verifier.cpp --- a/hotspot/src/share/vm/classfile/verifier.cpp Tue Nov 10 04:37:35 2015 +0000 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Tue Nov 10 08:42:53 2015 -0500 @@ -2846,7 +2846,7 @@ if (sig_stream.type() != T_VOID) { if (method_name == vmSymbols::object_initializer_name()) { // method must have a void return type - /* Unreachable? Class file parser verifies that methods have + /* Unreachable? Class file parser verifies that methods with '<' have * void return */ verify_error(ErrorContext::bad_code(bci), "Return type must be void in method"); diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/test/runtime/classFileParserBug/BadInitMethod.java --- a/hotspot/test/runtime/classFileParserBug/BadInitMethod.java Tue Nov 10 04:37:35 2015 +0000 +++ b/hotspot/test/runtime/classFileParserBug/BadInitMethod.java Tue Nov 10 08:42:53 2015 -0500 @@ -26,29 +26,59 @@ * @test * @bug 8130669 * @summary VM prohibits methods with return values - * @compile ignoredClinit.jasm + * @compile nonvoidClinit.jasm + * @compile clinitNonStatic.jasm + * @compile clinitArg.jasm + * @compile clinitArg51.jasm * @compile badInit.jasm * @run main/othervm -Xverify:all BadInitMethod */ -// Test that a non-void method does not cause an exception to be -// thrown. But that a non-void method causes a ClassFormatError -// exception. +// Test that non-void , non-static , and non-void +// methods cause ClassFormatException's to be thrown. public class BadInitMethod { public static void main(String args[]) throws Throwable { System.out.println("Regression test for bug 8130669"); try { - Class newClass = Class.forName("ignoredClinit"); - } catch (java.lang.Throwable e) { - throw new RuntimeException("Unexpected exception: " + e.getMessage()); + Class newClass = Class.forName("nonvoidClinit"); + throw new RuntimeException( + "Expected ClassFormatError exception for non-void not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadInitMethod passed for non-void "); + } + + try { + Class newClass = Class.forName("clinitNonStatic"); + throw new RuntimeException( + "Expected ClassFormatError exception for non-static not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadInitMethod passed for non-static "); + } + + // with args is allowed in class file version < 51. + try { + Class newClass = Class.forName("clinitArg"); + } catch (java.lang.ClassFormatError e) { + throw new RuntimeException( + "Unexpected ClassFormatError exception for with argument in class file < 51"); + } + + // with args is not allowed in class file version >= 51. + try { + Class newClass = Class.forName("clinitArg51"); + throw new RuntimeException( + "Expected ClassFormatError exception for with argument not thrown"); + } catch (java.lang.ClassFormatError e) { + System.out.println("Test BadInitMethod passed for with argument"); } try { Class newClass = Class.forName("badInit"); - throw new RuntimeException("Expected ClassFormatError exception not thrown"); + throw new RuntimeException( + "Expected ClassFormatError exception for non-void not thrown"); } catch (java.lang.ClassFormatError e) { - System.out.println("Test BadInitMethod passed"); + System.out.println("Test BadInitMethod passed for non-void "); } } } diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/test/runtime/classFileParserBug/clinitArg.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/clinitArg.jasm Tue Nov 10 08:42:53 2015 -0500 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +// This class contains a method with signature: (I)V. The JVM should +// not throw ClassFormatError because methods named that have arguments +// are not illegal in class file versions < 51. + +public class clinitArg version 50:0 +{ + + public static Method "":"(I)V" + stack 1 locals 1 + { + iconst_0; + return; + } + +} // end Class clinitArg diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/test/runtime/classFileParserBug/clinitArg51.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/clinitArg51.jasm Tue Nov 10 08:42:53 2015 -0500 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +// This class contains a method with signature: (I)V. The JVM should +// throw ClassFormatError because methods named that have arguments +// are illegal in class file version >= 51. + +public class clinitArg51 version 51:0 +{ + + public static Method "":"(I)V" + stack 1 locals 1 + { + iconst_0; + return; + } + +} // end Class clinitArg51 diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/test/runtime/classFileParserBug/clinitNonStatic.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/clinitNonStatic.jasm Tue Nov 10 08:42:53 2015 -0500 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +// This class contains a non-static method. The JVM should +// throw ClassFormatError because methods named must be static +// in class file versions >= 51. + +public class clinitNonStatic version 51:0 +{ + + public Method "":"()V" + stack 1 locals 1 + { + iconst_0; + return; + } + +} // end Class clinitNonStatic diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm --- a/hotspot/test/runtime/classFileParserBug/ignoredClinit.jasm Tue Nov 10 04:37:35 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2015, 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. - * - */ - -// This class contains a method with signature: ()I. The JVM should -// not complain about this because methods named that have arguments -// and/or are not void should be ignored by the JVM. - -public class ignoredClinit version 51:0 -{ - - public static Method "":"()I" - stack 1 locals 1 - { - iconst_0; - ireturn; - } - -} // end Class ignoredClinit diff -r 8745ee8ac1db -r 77ebbd9b0ecc hotspot/test/runtime/classFileParserBug/nonvoidClinit.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/classFileParserBug/nonvoidClinit.jasm Tue Nov 10 08:42:53 2015 -0500 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +// This class contains a method with signature: ()I. The JVM should +// throw ClassFormatError because methods named that are not void +// are illegal. + +public class nonvoidClinit version 51:0 +{ + + public static Method "":"()I" + stack 1 locals 1 + { + iconst_0; + ireturn; + } + +} // end Class nonvoidClinit