Skip to content

On JDK 21, ClassfileParser doesn't handle MethodParameter attributes without names #12783

Closed
@cushon

Description

@cushon

I'm seeing bad constant pool index: 0 crashes in scala with the latests OpenJDK 21 EA builds, with stack traces like:

	at scala.reflect.internal.Reporting.abort(Reporting.scala:69)
	at scala.reflect.internal.Reporting.abort$(Reporting.scala:65)
	at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:28)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$ConstantPool.errorBadIndex(ClassfileParser.scala:385)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$ConstantPool.getExternalName(ClassfileParser.scala:249)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.readParamNames$1(ClassfileParser.scala:828)

The latest JDK 21 EA builds contain some system classes with MethodParameters attributes that contain empty names. This change was caused by the fix for JDK-8292275: javac does not emit SYNTHETIC and MANDATED flags for parameters by default.

This was allowed by the specification in earlier versions, but wasn't used in practice (at least by the JDK), and some class reading implementations made the assumption that the name was always present.

The relevant part of the JVMS is:

If the value of the name_index item is zero, then this parameters element indicates a formal parameter with no name.

https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-4.html#jvms-4.7.24

I think this is the logic that needs updating:

https://github.com/scala/scala/blob/0e30133df211bc383fb8c7b7f8f4162f514f5aad/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala#L843

The fix is probably something like:

        case tpnme.MethodParametersATTR =>
          def readParamNames(): Unit = {
            val paramCount = u1()
            val paramNames = new Array[NameOrString](paramCount)
            val paramNameAccess = new Array[Int](paramCount)
            var i = 0
            while (i < paramCount) {
-              paramNames(i) = pool.getExternalName(u2())
+              val paramIndex = u2()
+              paramNames(i) = if (paramIndex == 0) null else pool.getExternalName(paramIndex)

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions