Skip to content

Commit 72a4900

Browse files
author
David Holmes
committedAug 28, 2024
8338888: SystemDictionary::class_name_symbol has incorrect length check
Reviewed-by: stuefe, kbarrett, coleenp
1 parent a8ac287 commit 72a4900

File tree

3 files changed

+98
-16
lines changed

3 files changed

+98
-16
lines changed
 

‎src/hotspot/share/classfile/systemDictionary.cpp

+22-7
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,32 @@ Symbol* SystemDictionary::class_name_symbol(const char* name, Symbol* exception,
261261
if (name == nullptr) {
262262
THROW_MSG_NULL(exception, "No class name given");
263263
}
264-
if ((int)strlen(name) > Symbol::max_length()) {
264+
size_t name_len = strlen(name);
265+
if (name_len > static_cast<size_t>(Symbol::max_length())) {
265266
// It's impossible to create this class; the name cannot fit
266-
// into the constant pool.
267-
Exceptions::fthrow(THREAD_AND_LOCATION, exception,
268-
"Class name exceeds maximum length of %d: %s",
269-
Symbol::max_length(),
270-
name);
267+
// into the constant pool. If necessary report an abridged name
268+
// in the exception message.
269+
if (name_len > static_cast<size_t>(MaxStringPrintSize)) {
270+
Exceptions::fthrow(THREAD_AND_LOCATION, exception,
271+
"Class name exceeds maximum length of %d: %.*s ... (%zu characters omitted) ... %.*s",
272+
Symbol::max_length(),
273+
MaxStringPrintSize / 2,
274+
name,
275+
name_len - 2 * (MaxStringPrintSize / 2), // allows for odd value
276+
MaxStringPrintSize / 2,
277+
name + name_len - MaxStringPrintSize / 2);
278+
}
279+
else {
280+
Exceptions::fthrow(THREAD_AND_LOCATION, exception,
281+
"Class name exceeds maximum length of %d: %s",
282+
Symbol::max_length(),
283+
name);
284+
}
271285
return nullptr;
272286
}
273287
// Callers should ensure that the name is never an illegal UTF8 string.
274-
assert(UTF8::is_legal_utf8((const unsigned char*)name, (int)strlen(name), false),
288+
assert(UTF8::is_legal_utf8((const unsigned char*)name,
289+
static_cast<int>(name_len), false),
275290
"Class name is not a valid utf8 string.");
276291

277292
// Make a new symbol for the class name.

‎test/hotspot/jtreg/runtime/exceptionMsgs/NoClassDefFoundError/NoClassDefFoundErrorTest.java

+40-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,21 +23,27 @@
2323

2424
/*
2525
* @test
26-
* @bug 8056900
26+
* @bug 8056900 8338888
2727
* @summary Verifies message returned with NoClassDefFoundError exception.
2828
* @library /test/lib
2929
* @modules java.base/jdk.internal.misc
3030
* java.compiler
31-
* @run main/native NoClassDefFoundErrorTest
31+
* @run main/native/othervm -Xlog:exceptions=info NoClassDefFoundErrorTest
3232
*/
3333

3434
import jdk.test.lib.compiler.InMemoryJavaCompiler;
3535
import jdk.internal.misc.Unsafe;
3636

3737
public class NoClassDefFoundErrorTest {
3838

39+
// Use the specified name
3940
static native void callDefineClass(String className);
4041
static native void callFindClass(String className);
42+
// Use a name longer than a Java string - returns false
43+
// if native allocation failed.
44+
static native boolean tryCallDefineClass();
45+
static native boolean tryCallFindClass();
46+
4147
static {
4248
System.loadLibrary("NoClassDefFoundErrorTest");
4349
}
@@ -54,7 +60,7 @@ public static void main(String args[]) throws Exception {
5460
tooBigClassName = tooBigClassName.append(tooBigClassName);
5561
}
5662

57-
// Test JVM_DefineClass() with long name.
63+
System.out.println("Test JVM_DefineClass() with long name");
5864
try {
5965
unsafe.defineClass(tooBigClassName.toString(), klassbuf, 4, klassbuf.length - 4, null, null);
6066
throw new RuntimeException("defineClass did not throw expected NoClassDefFoundError");
@@ -64,7 +70,7 @@ public static void main(String args[]) throws Exception {
6470
}
6571
}
6672

67-
// Test JNI_DefineClass() with long name.
73+
System.out.println("Test JNI_DefineClass() with long name");
6874
try {
6975
callDefineClass(tooBigClassName.toString());
7076
throw new RuntimeException("DefineClass did not throw expected NoClassDefFoundError");
@@ -74,17 +80,17 @@ public static void main(String args[]) throws Exception {
7480
}
7581
}
7682

77-
// Test JNI_FindClass() with long name.
83+
System.out.println("Test JNI_FindClass() with long name");
7884
try {
7985
callFindClass(tooBigClassName.toString());
80-
throw new RuntimeException("DefineClass did not throw expected NoClassDefFoundError");
86+
throw new RuntimeException("FindClass did not throw expected NoClassDefFoundError");
8187
} catch (NoClassDefFoundError e) {
8288
if (!e.getMessage().contains("Class name exceeds maximum length of ")) {
8389
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
8490
}
8591
}
8692

87-
// Test JNI_FindClass() with null name.
93+
System.out.println("Test JNI_FindClass() with null name");
8894
try {
8995
callFindClass(null);
9096
throw new RuntimeException("FindClass did not throw expected NoClassDefFoundError");
@@ -93,5 +99,31 @@ public static void main(String args[]) throws Exception {
9399
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
94100
}
95101
}
102+
103+
System.out.println("Test JNI_DefineClass() with giant name");
104+
try {
105+
if (tryCallDefineClass()) {
106+
throw new RuntimeException("DefineClass did not throw expected NoClassDefFoundError");
107+
} else {
108+
System.out.println("Test skipped due to native allocation failure");
109+
}
110+
} catch (NoClassDefFoundError e) {
111+
if (!e.getMessage().contains("Class name exceeds maximum length of ")) {
112+
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
113+
}
114+
}
115+
116+
System.out.println("Test JNI_FindClass() with giant name");
117+
try {
118+
if (tryCallFindClass()) {
119+
throw new RuntimeException("FindClass did not throw expected NoClassDefFoundError");
120+
} else {
121+
System.out.println("Test skipped due to native allocation failure");
122+
}
123+
} catch (NoClassDefFoundError e) {
124+
if (!e.getMessage().contains("Class name exceeds maximum length of ")) {
125+
throw new RuntimeException("Wrong NoClassDefFoundError: " + e.getMessage());
126+
}
127+
}
96128
}
97129
}

‎test/hotspot/jtreg/runtime/exceptionMsgs/NoClassDefFoundError/libNoClassDefFoundErrorTest.c

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,10 @@
2222
*/
2323

2424
#include <jni.h>
25+
#include <limits.h>
26+
#include <stdlib.h>
27+
#include <string.h>
28+
2529

2630
JNIEXPORT void JNICALL
2731
Java_NoClassDefFoundErrorTest_callDefineClass(JNIEnv *env, jclass klass, jstring className) {
@@ -42,3 +46,34 @@ Java_NoClassDefFoundErrorTest_callFindClass(JNIEnv *env, jclass klass, jstring c
4246
}
4347

4448

49+
static char* giant_string() {
50+
size_t len = ((size_t)INT_MAX) + 3;
51+
char* c_name = malloc(len * sizeof(char));
52+
if (c_name != NULL) {
53+
memset(c_name, 'Y', len - 1);
54+
c_name[len - 1] = '\0';
55+
}
56+
return c_name;
57+
}
58+
59+
JNIEXPORT jboolean JNICALL
60+
Java_NoClassDefFoundErrorTest_tryCallDefineClass(JNIEnv *env, jclass klass) {
61+
char* c_name = giant_string();
62+
if (c_name != NULL) {
63+
(*env)->DefineClass(env, c_name, NULL, NULL, 0);
64+
free(c_name);
65+
return JNI_TRUE;
66+
}
67+
return JNI_FALSE;
68+
}
69+
70+
JNIEXPORT jboolean JNICALL
71+
Java_NoClassDefFoundErrorTest_tryCallFindClass(JNIEnv *env, jclass klass) {
72+
char* c_name = giant_string();
73+
if (c_name != NULL) {
74+
jclass cls = (*env)->FindClass(env, c_name);
75+
free(c_name);
76+
return JNI_TRUE;
77+
}
78+
return JNI_FALSE;
79+
}

0 commit comments

Comments
 (0)
Please sign in to comment.