Skip to content

Commit 8de158a

Browse files
author
David Holmes
committed
8339134: Callers of Exceptions::fthrow should ensure exception message lengths avoid the INT_MAX limits of os::vsnprintf
Reviewed-by: coleenp, jsjolen
1 parent df2d4c1 commit 8de158a

File tree

9 files changed

+49
-6
lines changed

9 files changed

+49
-6
lines changed

src/hotspot/share/classfile/classFileError.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
PRAGMA_DIAG_PUSH
3535
PRAGMA_FORMAT_NONLITERAL_IGNORED
3636

37+
// None of the error routines below take in a free-form, potentially unbounded
38+
// string, and names are all limited to < 64K, so we know that all formatted
39+
// strings passed to fthrow will not be excessively large.
40+
3741
void ClassFileParser::classfile_parse_error(const char* msg, TRAPS) const {
3842
assert(_class_name != nullptr, "invariant");
3943
ResourceMark rm(THREAD);

src/hotspot/share/classfile/classFileParser.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,6 +1794,7 @@ void ClassFileParser::throwIllegalSignature(const char* type,
17941794
assert(sig != nullptr, "invariant");
17951795

17961796
ResourceMark rm(THREAD);
1797+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
17971798
Exceptions::fthrow(THREAD_AND_LOCATION,
17981799
vmSymbols::java_lang_ClassFormatError(),
17991800
"%s \"%s\" in class %s has illegal signature \"%s\"", type,
@@ -4073,6 +4074,8 @@ void ClassFileParser::check_super_class_access(const InstanceKlass* this_klass,
40734074
char* msg = Reflection::verify_class_access_msg(this_klass,
40744075
InstanceKlass::cast(super),
40754076
vca_result);
4077+
4078+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
40764079
if (msg == nullptr) {
40774080
bool same_module = (this_klass->module() == super->module());
40784081
Exceptions::fthrow(
@@ -4121,6 +4124,8 @@ void ClassFileParser::check_super_interface_access(const InstanceKlass* this_kla
41214124
char* msg = Reflection::verify_class_access_msg(this_klass,
41224125
k,
41234126
vca_result);
4127+
4128+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
41244129
if (msg == nullptr) {
41254130
bool same_module = (this_klass->module() == k->module());
41264131
Exceptions::fthrow(
@@ -4217,6 +4222,8 @@ static void check_illegal_static_method(const InstanceKlass* this_klass, TRAPS)
42174222
// if m is static and not the init method, throw a verify error
42184223
if ((m->is_static()) && (m->name() != vmSymbols::class_initializer_name())) {
42194224
ResourceMark rm(THREAD);
4225+
4226+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
42204227
Exceptions::fthrow(
42214228
THREAD_AND_LOCATION,
42224229
vmSymbols::java_lang_VerifyError(),
@@ -4236,6 +4243,7 @@ void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const {
42364243
assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set");
42374244
if (is_module) {
42384245
ResourceMark rm(THREAD);
4246+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
42394247
Exceptions::fthrow(
42404248
THREAD_AND_LOCATION,
42414249
vmSymbols::java_lang_NoClassDefFoundError(),
@@ -4259,6 +4267,7 @@ void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const {
42594267
(is_interface && major_gte_1_5 && (is_super || is_enum)) ||
42604268
(!is_interface && major_gte_1_5 && is_annotation)) {
42614269
ResourceMark rm(THREAD);
4270+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
42624271
Exceptions::fthrow(
42634272
THREAD_AND_LOCATION,
42644273
vmSymbols::java_lang_ClassFormatError(),
@@ -4295,6 +4304,7 @@ void ClassFileParser::verify_class_version(u2 major, u2 minor, Symbol* class_nam
42954304
}
42964305

42974306
if (major > max_version) {
4307+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
42984308
Exceptions::fthrow(
42994309
THREAD_AND_LOCATION,
43004310
vmSymbols::java_lang_UnsupportedClassVersionError(),
@@ -4310,6 +4320,7 @@ void ClassFileParser::verify_class_version(u2 major, u2 minor, Symbol* class_nam
43104320

43114321
if (minor == JAVA_PREVIEW_MINOR_VERSION) {
43124322
if (major != max_version) {
4323+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
43134324
Exceptions::fthrow(
43144325
THREAD_AND_LOCATION,
43154326
vmSymbols::java_lang_UnsupportedClassVersionError(),
@@ -4362,6 +4373,7 @@ void ClassFileParser::verify_legal_field_modifiers(jint flags,
43624373

43634374
if (is_illegal) {
43644375
ResourceMark rm(THREAD);
4376+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
43654377
Exceptions::fthrow(
43664378
THREAD_AND_LOCATION,
43674379
vmSymbols::java_lang_ClassFormatError(),
@@ -4445,6 +4457,7 @@ void ClassFileParser::verify_legal_method_modifiers(jint flags,
44454457

44464458
if (is_illegal) {
44474459
ResourceMark rm(THREAD);
4460+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
44484461
Exceptions::fthrow(
44494462
THREAD_AND_LOCATION,
44504463
vmSymbols::java_lang_ClassFormatError(),
@@ -4686,6 +4699,7 @@ void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPS) const {
46864699
if (!legal) {
46874700
ResourceMark rm(THREAD);
46884701
assert(_class_name != nullptr, "invariant");
4702+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
46894703
Exceptions::fthrow(
46904704
THREAD_AND_LOCATION,
46914705
vmSymbols::java_lang_ClassFormatError(),
@@ -4719,6 +4733,7 @@ void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPS) const {
47194733
if (!legal) {
47204734
ResourceMark rm(THREAD);
47214735
assert(_class_name != nullptr, "invariant");
4736+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
47224737
Exceptions::fthrow(
47234738
THREAD_AND_LOCATION,
47244739
vmSymbols::java_lang_ClassFormatError(),
@@ -4756,6 +4771,7 @@ void ClassFileParser::verify_legal_method_name(const Symbol* name, TRAPS) const
47564771
if (!legal) {
47574772
ResourceMark rm(THREAD);
47584773
assert(_class_name != nullptr, "invariant");
4774+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
47594775
Exceptions::fthrow(
47604776
THREAD_AND_LOCATION,
47614777
vmSymbols::java_lang_ClassFormatError(),
@@ -5527,6 +5543,7 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
55275543
if (_class_name != class_name_in_cp) {
55285544
if (_class_name != vmSymbols::unknown_class_name()) {
55295545
ResourceMark rm(THREAD);
5546+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
55305547
Exceptions::fthrow(THREAD_AND_LOCATION,
55315548
vmSymbols::java_lang_NoClassDefFoundError(),
55325549
"%s (wrong name: %s)",

src/hotspot/share/interpreter/linkResolver.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ void LinkResolver::check_klass_accessibility(Klass* ref_klass, Klass* sel_klass,
323323
char* msg = Reflection::verify_class_access_msg(ref_klass,
324324
InstanceKlass::cast(base_klass),
325325
vca_result);
326+
327+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
328+
326329
bool same_module = (base_klass->module() == ref_klass->module());
327330
if (msg == nullptr) {
328331
Exceptions::fthrow(
@@ -615,6 +618,7 @@ void LinkResolver::check_method_accessability(Klass* ref_klass,
615618
print_nest_host_error_on(&ss, ref_klass, sel_klass);
616619
}
617620

621+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
618622
Exceptions::fthrow(THREAD_AND_LOCATION,
619623
vmSymbols::java_lang_IllegalAccessError(),
620624
"%s",
@@ -968,6 +972,7 @@ void LinkResolver::check_field_accessability(Klass* ref_klass,
968972
if (fd.is_private()) {
969973
print_nest_host_error_on(&ss, ref_klass, sel_klass);
970974
}
975+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
971976
Exceptions::fthrow(THREAD_AND_LOCATION,
972977
vmSymbols::java_lang_IllegalAccessError(),
973978
"%s",
@@ -1187,6 +1192,7 @@ Method* LinkResolver::linktime_resolve_special_method(const LinkInfo& link_info,
11871192
ss.print(" %s(", resolved_method->name()->as_C_string());
11881193
resolved_method->signature()->print_as_signature_external_parameters(&ss);
11891194
ss.print(")' not found");
1195+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
11901196
Exceptions::fthrow(
11911197
THREAD_AND_LOCATION,
11921198
vmSymbols::java_lang_NoSuchMethodError(),

src/hotspot/share/oops/constantPool.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,7 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
12661266
cp_index,
12671267
callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef",
12681268
callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef");
1269+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
12691270
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IncompatibleClassChangeError(), "%s", ss.as_string());
12701271
save_and_throw_exception(this_cp, cp_index, tag, CHECK_NULL);
12711272
}

src/hotspot/share/oops/instanceKlass.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ bool InstanceKlass::link_class_impl(TRAPS) {
899899
// if we are executing Java code. This is not a problem for CDS dumping phase since
900900
// it doesn't execute any Java code.
901901
ResourceMark rm(THREAD);
902+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
902903
Exceptions::fthrow(THREAD_AND_LOCATION,
903904
vmSymbols::java_lang_NoClassDefFoundError(),
904905
"Class %s, or one of its supertypes, failed class initialization",
@@ -919,6 +920,7 @@ bool InstanceKlass::link_class_impl(TRAPS) {
919920
if (super_klass != nullptr) {
920921
if (super_klass->is_interface()) { // check if super class is an interface
921922
ResourceMark rm(THREAD);
923+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
922924
Exceptions::fthrow(
923925
THREAD_AND_LOCATION,
924926
vmSymbols::java_lang_IncompatibleClassChangeError(),
@@ -3286,6 +3288,7 @@ InstanceKlass* InstanceKlass::compute_enclosing_class(bool* inner_is_member, TRA
32863288
// If the outer class is not an instance klass then it cannot have
32873289
// declared any inner classes.
32883290
ResourceMark rm(THREAD);
3291+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
32893292
Exceptions::fthrow(
32903293
THREAD_AND_LOCATION,
32913294
vmSymbols::java_lang_IncompatibleClassChangeError(),

src/hotspot/share/runtime/reflection.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ void Reflection::check_for_inner_class(const InstanceKlass* outer, const Instanc
697697

698698
// 'inner' not declared as an inner klass in outer
699699
ResourceMark rm(THREAD);
700+
// Names are all known to be < 64k so we know this formatted message is not excessively large.
700701
Exceptions::fthrow(
701702
THREAD_AND_LOCATION,
702703
vmSymbols::java_lang_IncompatibleClassChangeError(),

src/hotspot/share/services/diagnosticArgument.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,13 @@ template <> void DCmdArgument<jlong>::parse_value(const char* str,
115115
|| sscanf(str, JLONG_FORMAT "%n", &_value, &scanned) != 1
116116
|| (size_t)scanned != len)
117117
{
118-
const int maxprint = 64;
119118
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
120-
"Integer parsing error in command argument '%s'. Could not parse: %.*s%s.\n", _name,
121-
MIN2((int)len, maxprint),
122-
(str == nullptr ? "<null>" : str),
123-
(len > maxprint ? "..." : ""));
119+
"Integer parsing error in command argument '%.*s'. Could not parse: %.*s%s.\n",
120+
maxprint,
121+
_name,
122+
maxprint > len ? (int)len : maxprint,
123+
(str == nullptr ? "<null>" : str),
124+
(len > maxprint ? "..." : ""));
124125
}
125126
}
126127

@@ -160,7 +161,11 @@ PRAGMA_DIAG_POP
160161

161162
buf[len] = '\0';
162163
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
163-
"Boolean parsing error in command argument '%s'. Could not parse: %s.\n", _name, buf);
164+
"Boolean parsing error in command argument '%.*s'. Could not parse: %.*s.\n",
165+
maxprint,
166+
_name,
167+
maxprint,
168+
buf);
164169
}
165170
}
166171
}

src/hotspot/share/services/diagnosticArgument.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class MemorySizeArgument {
6262

6363
class GenDCmdArgument : public ResourceObj {
6464
protected:
65+
static const int maxprint = 64;
6566
GenDCmdArgument* _next;
6667
const char* const _name;
6768
const char* const _description;

src/hotspot/share/utilities/exceptions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ void Exceptions::throw_stack_overflow_exception(JavaThread* THREAD, const char*
258258
_throw(THREAD, file, line, exception);
259259
}
260260

261+
// All callers are expected to have ensured that the incoming expanded format string
262+
// will be within reasonable limits - specifically we will never hit the INT_MAX limit
263+
// of os::vsnprintf when it tries to report how big a buffer is needed. Even so we
264+
// further limit the formatted output to 1024 characters.
261265
void Exceptions::fthrow(JavaThread* thread, const char* file, int line, Symbol* h_name, const char* format, ...) {
262266
const int max_msg_size = 1024;
263267
va_list ap;
@@ -273,6 +277,7 @@ void Exceptions::fthrow(JavaThread* thread, const char* file, int line, Symbol*
273277
// have a truncated UTF-8 sequence. Similarly, if the buffer was too small and ret >= max_msg_size
274278
// we may also have a truncated UTF-8 sequence. In such cases we need to fix the buffer so the UTF-8
275279
// sequence is valid.
280+
assert(ret != -1, "Caller should have ensured the incoming format string is size limited!");
276281
if (ret == -1 || ret >= max_msg_size) {
277282
int len = (int) strlen(msg);
278283
if (len > 0) {

0 commit comments

Comments
 (0)