mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8139164: JVM should throw ClassFormatError for non-void methods named <clinit>
If method being parsed is named <clinit>, throw ClassFormatError if it is not void or has arguments, for class file version >= 51. Reviewed-by: acorn, lfoltan
This commit is contained in:
parent
fd47033053
commit
3756d55ee6
7 changed files with 173 additions and 19 deletions
|
@ -92,6 +92,7 @@
|
|||
|
||||
// Used for backward compatibility reasons:
|
||||
// - to check NameAndType_info signatures more aggressively
|
||||
// - to disallow argument and require ACC_STATIC for <clinit> methods
|
||||
#define JAVA_7_VERSION 51
|
||||
|
||||
// Extension method support.
|
||||
|
@ -1997,9 +1998,7 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
|
|||
} 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 <clinit> 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 <clinit> is not static in class file %s", CHECK_(nullHandle));
|
||||
}
|
||||
} else {
|
||||
verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle));
|
||||
|
@ -5159,6 +5158,14 @@ int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signatu
|
|||
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 @@ int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signatu
|
|||
// The first non-signature thing better be a ')'
|
||||
if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) {
|
||||
length--;
|
||||
if (name == vmSymbols::object_initializer_name()) {
|
||||
// All "<init>" 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;
|
||||
}
|
||||
|
|
|
@ -2846,7 +2846,7 @@ void ClassVerifier::verify_invoke_instructions(
|
|||
if (sig_stream.type() != T_VOID) {
|
||||
if (method_name == vmSymbols::object_initializer_name()) {
|
||||
// <init> method must have a void return type
|
||||
/* Unreachable? Class file parser verifies that <init> 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 <init> method");
|
||||
|
|
|
@ -26,29 +26,59 @@
|
|||
* @test
|
||||
* @bug 8130669
|
||||
* @summary VM prohibits <clinit> 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 <clinit> method does not cause an exception to be
|
||||
// thrown. But that a non-void <init> method causes a ClassFormatError
|
||||
// exception.
|
||||
// Test that non-void <clinit>, non-static <clinit>, and non-void
|
||||
// <init> 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 <clinit> not thrown");
|
||||
} catch (java.lang.ClassFormatError e) {
|
||||
System.out.println("Test BadInitMethod passed for non-void <clinit>");
|
||||
}
|
||||
|
||||
try {
|
||||
Class newClass = Class.forName("clinitNonStatic");
|
||||
throw new RuntimeException(
|
||||
"Expected ClassFormatError exception for non-static <clinit> not thrown");
|
||||
} catch (java.lang.ClassFormatError e) {
|
||||
System.out.println("Test BadInitMethod passed for non-static <clinit>");
|
||||
}
|
||||
|
||||
// <clinit> 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 <clinit> with argument in class file < 51");
|
||||
}
|
||||
|
||||
// <clinit> with args is not allowed in class file version >= 51.
|
||||
try {
|
||||
Class newClass = Class.forName("clinitArg51");
|
||||
throw new RuntimeException(
|
||||
"Expected ClassFormatError exception for <clinit> with argument not thrown");
|
||||
} catch (java.lang.ClassFormatError e) {
|
||||
System.out.println("Test BadInitMethod passed for <clinit> 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 <init> not thrown");
|
||||
} catch (java.lang.ClassFormatError e) {
|
||||
System.out.println("Test BadInitMethod passed");
|
||||
System.out.println("Test BadInitMethod passed for non-void <init>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
39
hotspot/test/runtime/classFileParserBug/clinitArg.jasm
Normal file
39
hotspot/test/runtime/classFileParserBug/clinitArg.jasm
Normal file
|
@ -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 <clinit> method with signature: (I)V. The JVM should
|
||||
// not throw ClassFormatError because methods named <clinit> that have arguments
|
||||
// are not illegal in class file versions < 51.
|
||||
|
||||
public class clinitArg version 50:0
|
||||
{
|
||||
|
||||
public static Method "<clinit>":"(I)V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
iconst_0;
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class clinitArg
|
39
hotspot/test/runtime/classFileParserBug/clinitArg51.jasm
Normal file
39
hotspot/test/runtime/classFileParserBug/clinitArg51.jasm
Normal file
|
@ -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 <clinit> method with signature: (I)V. The JVM should
|
||||
// throw ClassFormatError because methods named <clinit> that have arguments
|
||||
// are illegal in class file version >= 51.
|
||||
|
||||
public class clinitArg51 version 51:0
|
||||
{
|
||||
|
||||
public static Method "<clinit>":"(I)V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
iconst_0;
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class clinitArg51
|
39
hotspot/test/runtime/classFileParserBug/clinitNonStatic.jasm
Normal file
39
hotspot/test/runtime/classFileParserBug/clinitNonStatic.jasm
Normal file
|
@ -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 <clinit> method. The JVM should
|
||||
// throw ClassFormatError because methods named <clinit> must be static
|
||||
// in class file versions >= 51.
|
||||
|
||||
public class clinitNonStatic version 51:0
|
||||
{
|
||||
|
||||
public Method "<clinit>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
iconst_0;
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class clinitNonStatic
|
|
@ -23,10 +23,10 @@
|
|||
*/
|
||||
|
||||
// This class contains a <clinit> method with signature: ()I. The JVM should
|
||||
// not complain about this because methods named <clinit> that have arguments
|
||||
// and/or are not void should be ignored by the JVM.
|
||||
// throw ClassFormatError because methods named <clinit> that are not void
|
||||
// are illegal.
|
||||
|
||||
public class ignoredClinit version 51:0
|
||||
public class nonvoidClinit version 51:0
|
||||
{
|
||||
|
||||
public static Method "<clinit>":"()I"
|
||||
|
@ -36,4 +36,4 @@ public class ignoredClinit version 51:0
|
|||
ireturn;
|
||||
}
|
||||
|
||||
} // end Class ignoredClinit
|
||||
} // end Class nonvoidClinit
|
Loading…
Add table
Add a link
Reference in a new issue