8175383: JVM should throw NCDFE if ACC_MODULE and CONSTANT_Module/Package are set

If bad constant is seen, save it to throw CFE if ACC_MODULE is not in access_flags

Reviewed-by: dholmes, acorn, lfoltan, gtriantafill
This commit is contained in:
Harold Seigel 2017-03-06 09:45:58 -05:00
parent 5cdba20f81
commit b7121021af
4 changed files with 369 additions and 5 deletions

View file

@ -105,6 +105,12 @@
#define JAVA_9_VERSION 53
void ClassFileParser::set_class_bad_constant_seen(short bad_constant) {
assert((bad_constant == 19 || bad_constant == 20) && _major_version >= JAVA_9_VERSION,
"Unexpected bad constant pool entry");
if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant;
}
void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
ConstantPool* cp,
const int length,
@ -302,6 +308,18 @@ void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const s
}
break;
}
case 19:
case 20: {
// Record that an error occurred in these two cases but keep parsing so
// that ACC_Module can be checked for in the access_flags. Need to
// throw NoClassDefFoundError in that case.
if (_major_version >= JAVA_9_VERSION) {
cfs->guarantee_more(3, CHECK);
cfs->get_u2_fast();
set_class_bad_constant_seen(tag);
break;
}
}
default: {
classfile_parse_error("Unknown constant tag %u in class file %s",
tag,
@ -359,14 +377,18 @@ PRAGMA_DIAG_POP
#endif
void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
ConstantPool* const cp,
const int length,
TRAPS) {
ConstantPool* const cp,
const int length,
TRAPS) {
assert(cp != NULL, "invariant");
assert(stream != NULL, "invariant");
// parsing constant pool entries
parse_constant_pool_entries(stream, cp, length, CHECK);
if (class_bad_constant_seen() != 0) {
// a bad CP entry has been detected previously so stop parsing and just return.
return;
}
int index = 1; // declared outside of loops for portability
@ -5558,6 +5580,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_protection_domain(protection_domain),
_access_flags(),
_pub_level(pub_level),
_bad_constant_seen(0),
_synthetic_flag(false),
_sde_length(false),
_sde_buffer(NULL),
@ -5765,8 +5788,14 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
verify_legal_class_modifiers(flags, CHECK);
_access_flags.set_flags(flags);
short bad_constant = class_bad_constant_seen();
if (bad_constant != 0) {
// Do not throw CFE until after the access_flags are checked because if
// ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, CHECK);
}
_access_flags.set_flags(flags);
// This class and superclass
_this_class_index = stream->get_u2_fast();