8338888: SystemDictionary::class_name_symbol has incorrect length check
Reviewed-by: stuefe, kbarrett, coleenp
This commit is contained in:
parent
a8ac28725b
commit
72a49005ee
@ -261,17 +261,32 @@ Symbol* SystemDictionary::class_name_symbol(const char* name, Symbol* exception,
|
|||||||
if (name == nullptr) {
|
if (name == nullptr) {
|
||||||
THROW_MSG_NULL(exception, "No class name given");
|
THROW_MSG_NULL(exception, "No class name given");
|
||||||
}
|
}
|
||||||
if ((int)strlen(name) > Symbol::max_length()) {
|
size_t name_len = strlen(name);
|
||||||
|
if (name_len > static_cast<size_t>(Symbol::max_length())) {
|
||||||
// It's impossible to create this class; the name cannot fit
|
// It's impossible to create this class; the name cannot fit
|
||||||
// into the constant pool.
|
// into the constant pool. If necessary report an abridged name
|
||||||
Exceptions::fthrow(THREAD_AND_LOCATION, exception,
|
// in the exception message.
|
||||||
"Class name exceeds maximum length of %d: %s",
|
if (name_len > static_cast<size_t>(MaxStringPrintSize)) {
|
||||||
Symbol::max_length(),
|
Exceptions::fthrow(THREAD_AND_LOCATION, exception,
|
||||||
name);
|
"Class name exceeds maximum length of %d: %.*s ... (%zu characters omitted) ... %.*s",
|
||||||
|
Symbol::max_length(),
|
||||||
|
MaxStringPrintSize / 2,
|
||||||
|
name,
|
||||||
|
name_len - 2 * (MaxStringPrintSize / 2), // allows for odd value
|
||||||
|
MaxStringPrintSize / 2,
|
||||||
|
name + name_len - MaxStringPrintSize / 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Exceptions::fthrow(THREAD_AND_LOCATION, exception,
|
||||||
|
"Class name exceeds maximum length of %d: %s",
|
||||||
|
Symbol::max_length(),
|
||||||
|
name);
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// Callers should ensure that the name is never an illegal UTF8 string.
|
// Callers should ensure that the name is never an illegal UTF8 string.
|
||||||
assert(UTF8::is_legal_utf8((const unsigned char*)name, (int)strlen(name), false),
|
assert(UTF8::is_legal_utf8((const unsigned char*)name,
|
||||||
|
static_cast<int>(name_len), false),
|
||||||
"Class name is not a valid utf8 string.");
|
"Class name is not a valid utf8 string.");
|
||||||
|
|
||||||
// Make a new symbol for the class name.
|
// Make a new symbol for the class name.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,12 +23,12 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8056900
|
* @bug 8056900 8338888
|
||||||
* @summary Verifies message returned with NoClassDefFoundError exception.
|
* @summary Verifies message returned with NoClassDefFoundError exception.
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @modules java.base/jdk.internal.misc
|
* @modules java.base/jdk.internal.misc
|
||||||
* java.compiler
|
* java.compiler
|
||||||
* @run main/native NoClassDefFoundErrorTest
|
* @run main/native/othervm -Xlog:exceptions=info NoClassDefFoundErrorTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import jdk.test.lib.compiler.InMemoryJavaCompiler;
|
import jdk.test.lib.compiler.InMemoryJavaCompiler;
|
||||||
@ -36,8 +36,14 @@ import jdk.internal.misc.Unsafe;
|
|||||||
|
|
||||||
public class NoClassDefFoundErrorTest {
|
public class NoClassDefFoundErrorTest {
|
||||||
|
|
||||||
|
// Use the specified name
|
||||||
static native void callDefineClass(String className);
|
static native void callDefineClass(String className);
|
||||||
static native void callFindClass(String className);
|
static native void callFindClass(String className);
|
||||||
|
// Use a name longer than a Java string - returns false
|
||||||
|
// if native allocation failed.
|
||||||
|
static native boolean tryCallDefineClass();
|
||||||
|
static native boolean tryCallFindClass();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.loadLibrary("NoClassDefFoundErrorTest");
|
System.loadLibrary("NoClassDefFoundErrorTest");
|
||||||
}
|
}
|
||||||
@ -54,7 +60,7 @@ public class NoClassDefFoundErrorTest {
|
|||||||
tooBigClassName = tooBigClassName.append(tooBigClassName);
|
tooBigClassName = tooBigClassName.append(tooBigClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test JVM_DefineClass() with long name.
|
System.out.println("Test JVM_DefineClass() with long name");
|
||||||
try {
|
try {
|
||||||
unsafe.defineClass(tooBigClassName.toString(), klassbuf, 4, klassbuf.length - 4, null, null);
|
unsafe.defineClass(tooBigClassName.toString(), klassbuf, 4, klassbuf.length - 4, null, null);
|
||||||
throw new RuntimeException("defineClass did not throw expected NoClassDefFoundError");
|
throw new RuntimeException("defineClass did not throw expected NoClassDefFoundError");
|
||||||
@ -64,7 +70,7 @@ public class NoClassDefFoundErrorTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test JNI_DefineClass() with long name.
|
System.out.println("Test JNI_DefineClass() with long name");
|
||||||
try {
|
try {
|
||||||
callDefineClass(tooBigClassName.toString());
|
callDefineClass(tooBigClassName.toString());
|
||||||
throw new RuntimeException("DefineClass did not throw expected NoClassDefFoundError");
|
throw new RuntimeException("DefineClass did not throw expected NoClassDefFoundError");
|
||||||
@ -74,17 +80,17 @@ public class NoClassDefFoundErrorTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test JNI_FindClass() with long name.
|
System.out.println("Test JNI_FindClass() with long name");
|
||||||
try {
|
try {
|
||||||
callFindClass(tooBigClassName.toString());
|
callFindClass(tooBigClassName.toString());
|
||||||
throw new RuntimeException("DefineClass did not throw expected NoClassDefFoundError");
|
throw new RuntimeException("FindClass did not throw expected NoClassDefFoundError");
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
if (!e.getMessage().contains("Class name exceeds maximum length of ")) {
|
if (!e.getMessage().contains("Class name exceeds maximum length of ")) {
|
||||||
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
|
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test JNI_FindClass() with null name.
|
System.out.println("Test JNI_FindClass() with null name");
|
||||||
try {
|
try {
|
||||||
callFindClass(null);
|
callFindClass(null);
|
||||||
throw new RuntimeException("FindClass did not throw expected NoClassDefFoundError");
|
throw new RuntimeException("FindClass did not throw expected NoClassDefFoundError");
|
||||||
@ -93,5 +99,31 @@ public class NoClassDefFoundErrorTest {
|
|||||||
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
|
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("Test JNI_DefineClass() with giant name");
|
||||||
|
try {
|
||||||
|
if (tryCallDefineClass()) {
|
||||||
|
throw new RuntimeException("DefineClass did not throw expected NoClassDefFoundError");
|
||||||
|
} else {
|
||||||
|
System.out.println("Test skipped due to native allocation failure");
|
||||||
|
}
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
if (!e.getMessage().contains("Class name exceeds maximum length of ")) {
|
||||||
|
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Test JNI_FindClass() with giant name");
|
||||||
|
try {
|
||||||
|
if (tryCallFindClass()) {
|
||||||
|
throw new RuntimeException("FindClass did not throw expected NoClassDefFoundError");
|
||||||
|
} else {
|
||||||
|
System.out.println("Test skipped due to native allocation failure");
|
||||||
|
}
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
if (!e.getMessage().contains("Class name exceeds maximum length of ")) {
|
||||||
|
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -22,6 +22,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_NoClassDefFoundErrorTest_callDefineClass(JNIEnv *env, jclass klass, jstring className) {
|
Java_NoClassDefFoundErrorTest_callDefineClass(JNIEnv *env, jclass klass, jstring className) {
|
||||||
@ -42,3 +46,34 @@ Java_NoClassDefFoundErrorTest_callFindClass(JNIEnv *env, jclass klass, jstring c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char* giant_string() {
|
||||||
|
size_t len = ((size_t)INT_MAX) + 3;
|
||||||
|
char* c_name = malloc(len * sizeof(char));
|
||||||
|
if (c_name != NULL) {
|
||||||
|
memset(c_name, 'Y', len - 1);
|
||||||
|
c_name[len - 1] = '\0';
|
||||||
|
}
|
||||||
|
return c_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_NoClassDefFoundErrorTest_tryCallDefineClass(JNIEnv *env, jclass klass) {
|
||||||
|
char* c_name = giant_string();
|
||||||
|
if (c_name != NULL) {
|
||||||
|
(*env)->DefineClass(env, c_name, NULL, NULL, 0);
|
||||||
|
free(c_name);
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_NoClassDefFoundErrorTest_tryCallFindClass(JNIEnv *env, jclass klass) {
|
||||||
|
char* c_name = giant_string();
|
||||||
|
if (c_name != NULL) {
|
||||||
|
jclass cls = (*env)->FindClass(env, c_name);
|
||||||
|
free(c_name);
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user