Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
cushon opened this issue May 9, 2023 · 7 comments
Assignees
Labels
Milestone

Comments

@cushon
Copy link

cushon commented May 9, 2023

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)
@SethTisue
Copy link
Member

Thanks for the report — it's well timed, since there's likely still time for a fix to make the upcoming 2.13.11 release.

@SethTisue
Copy link
Member

not sure if null or "" is more appropriate here

@SethTisue
Copy link
Member

for reference, scala/scala#4735 is where the support originally landed

@SethTisue
Copy link
Member

SethTisue commented May 16, 2023

a quick way to reproduce the problem without involving sbt is simply to open the Scala REPL (using the default scala or scala-cli)

regardless, we should have a failing unit test that targets the issue specifically

reminder to self: Scala 3 will need the same fix

@SethTisue
Copy link
Member

SethTisue commented May 16, 2023

not sure if null or "" is more appropriate here

using "" (or rather, new NameOrString("")) seems implausible given that we later do param.name = paramNames.names(i).name.toTermName.encode (line 1357) — probably better to use null and then guard against it downstream — with any luck, line 1357 is the only place a guard would be needed

@SethTisue
Copy link
Member

regardless, we should have a failing unit test that targets the issue specifically

or not... the problem affects the compiler itself, so any compiler on which this hypothetical unit test would fail, is a compiler that wouldn't even be able to compile the unit test

@som-snytt
Copy link

I've been through the desert on an arg with no name.

@SethTisue SethTisue modified the milestones: 2.13.11, 2.12.18 May 17, 2023
@SethTisue SethTisue changed the title ClassfileParser doesn't handle MethodParameter attributes without names On JDK 21, ClassfileParser doesn't handle MethodParameter attributes without names May 18, 2023
SethTisue added a commit to SethTisue/scala that referenced this issue May 18, 2023
they won't pass until we're using a Scala 3 release that has a fix for
scala/bug#12783
SethTisue added a commit to SethTisue/dotty that referenced this issue May 19, 2023
this is a forward port of scala/scala#10397 (fixing scala/bug#12783,
from which Scala 3 also suffers)
smarter added a commit to scala/scala3 that referenced this issue May 22, 2023
this is a forward port of scala/scala#10397 (fixing scala/bug#12783,
from which Scala 3 also suffers) — the same fix we'll be shipping in
2.12.18 and 2.13.11

I haven't included a unit test, because
* a similar change has already been well validated in a Scala 2 context
* without this change, the compiler can't compile anything at all on JDK
21
* we need the reference compiler to include this change before we can
bootstrap on JDK 21 anyway

but I did manually test it locally, by bootstrapping on JDK 11,
publishing the resulting compiler locally, and then launching the REPL
and evaluating `2 + 2`

on 3.3.0-RC6, that fails with:

> error while loading AccessFlag,
> class file /modules/java.base/java/lang/reflect/AccessFlag.class is
broken, reading aborted with class java.lang.RuntimeException
> bad constant pool index: 0 at pos: 5189
> error while loading ElementType,
> class file /modules/java.base/java/lang/annotation/ElementType.class
is broken, reading aborted with class java.lang.RuntimeException
> bad constant pool index: 0 at pos: 1220
> 2 errors found

whereas with this change, it succeeds.
G1ng3r pushed a commit to G1ng3r/dotty that referenced this issue Sep 10, 2023
this is a forward port of scala/scala#10397 (fixing scala/bug#12783,
from which Scala 3 also suffers)
sequencer added a commit to SpriteOvO/chisel that referenced this issue Oct 14, 2023
sequencer added a commit to SpriteOvO/chisel that referenced this issue Oct 14, 2023
sequencer added a commit to SpriteOvO/chisel that referenced this issue Oct 14, 2023
sequencer added a commit to SpriteOvO/chisel that referenced this issue Oct 14, 2023
mergify bot pushed a commit to chipsalliance/chisel that referenced this issue Oct 14, 2023
* Implement Verilog output stream `PanamaCIRCTConverter`

* Truncate or pad when connecting ports with different widths

* Use `scala.math.BigInt.bitLength` instead of our own `bitLength`

* Use correct module name for instances

* Binder introduces Firtool options

* fix binder for JDK21 and firtool 1.67.0

refer to:
- openjdk/jdk#13079
- llvm-project/circt dadf87b742f547840f6866beb50bdf46a76d3fed

* fix for review

* reformat

* bump GitHub CI to JDK 21 and mill 0.11.5

* remove 2.13.0 to 2.13.10 for JDK21 in build.sc

ref to: scala/bug#12783

---------

Co-authored-by: Jiuyang Liu <liu@jiuyang.me>
adkian-sifive pushed a commit to chipsalliance/chisel that referenced this issue Oct 16, 2023
* Implement Verilog output stream `PanamaCIRCTConverter`

* Truncate or pad when connecting ports with different widths

* Use `scala.math.BigInt.bitLength` instead of our own `bitLength`

* Use correct module name for instances

* Binder introduces Firtool options

* fix binder for JDK21 and firtool 1.67.0

refer to:
- openjdk/jdk#13079
- llvm-project/circt dadf87b742f547840f6866beb50bdf46a76d3fed

* fix for review

* reformat

* bump GitHub CI to JDK 21 and mill 0.11.5

* remove 2.13.0 to 2.13.10 for JDK21 in build.sc

ref to: scala/bug#12783

---------

Co-authored-by: Jiuyang Liu <liu@jiuyang.me>
SethTisue added a commit to SethTisue/scala that referenced this issue Jan 18, 2024
We'd added this to work around scala/bug#12783 ,
but sbt has taken the 2.12.18 upgrade now
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants