Skip to content

Commit

Permalink
classfile reader: handle JDK 9+ constant types in constant pool (#19533)
Browse files Browse the repository at this point in the history
forward-port of scala/scala#10675 and scala/scala#8595
references scala/bug#12396 and scala/bug#11635
fixes #19527 ("bad constant pool tag 17")
also fixes unreported potential "bad constant pool tag 19" and "bad constant pool tag 20" errors
  • Loading branch information
SethTisue committed Jan 30, 2024
2 parents 1ec17f6 + 26852de commit 7a5cb6e
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ object ClassfileConstants {

inline val CONSTANT_METHODHANDLE = 15
inline val CONSTANT_METHODTYPE = 16
inline val CONSTANT_DYNAMIC = 17
inline val CONSTANT_INVOKEDYNAMIC = 18
inline val CONSTANT_MODULE = 19
inline val CONSTANT_PACKAGE = 20

// tags describing the type of a literal in attribute values
inline val BYTE_TAG = 'B'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ object ClassfileParser {
(in.nextByte.toInt: @switch) match {
case CONSTANT_UTF8 | CONSTANT_UNICODE =>
in.skip(in.nextChar)
case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE =>
case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE
| CONSTANT_MODULE | CONSTANT_PACKAGE =>
in.skip(2)
case CONSTANT_METHODHANDLE =>
in.skip(3)
case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF
| CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT
| CONSTANT_INVOKEDYNAMIC =>
| CONSTANT_INVOKEDYNAMIC | CONSTANT_DYNAMIC =>
in.skip(4)
case CONSTANT_LONG | CONSTANT_DOUBLE =>
in.skip(8)
Expand Down
57 changes: 57 additions & 0 deletions compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package dotty.tools.backend.jvm

// painful to do Java reflection stuff without this
import scala.language.unsafeNulls

import org.junit.Assert.assertEquals
import org.junit.Test

import java.lang.reflect.Member

class ClassfileParserTest {
@Test
def noConstantPoolLag(): Unit = {
def constNames(ms: List[Member]) = ms.collect {
case f if f.getName.startsWith("CONSTANT_") => f.getName
}.sorted

val toDotc = Map(
"CONSTANT_INTERFACE_METHODREF" -> "CONSTANT_INTFMETHODREF",
"CONSTANT_INVOKE_DYNAMIC" -> "CONSTANT_INVOKEDYNAMIC",
"CONSTANT_METHOD_HANDLE" -> "CONSTANT_METHODHANDLE",
"CONSTANT_METHOD_TYPE" -> "CONSTANT_METHODTYPE",
"CONSTANT_NAME_AND_TYPE" -> "CONSTANT_NAMEANDTYPE",
).withDefault(x => x)

val asmConsts = constNames(Class.forName("scala.tools.asm.Symbol").getDeclaredFields.toList)
.map(_.stripSuffix("_TAG"))
.map(toDotc)
.::("CONSTANT_UNICODE")
.sorted
// in the Scala 2 version of this test, we also use Java reflection to get the constant
// names out of ClassfileConstants. in Dotty, the constants are `inline val`s, invisible
// to Java reflection, so we hardcode them here
assertEquals(asmConsts, List(
// do not add to this list without also making the corresponding change
// in ClassfileConstants! that would defeat the purpose of the test
"CONSTANT_CLASS",
"CONSTANT_DOUBLE",
"CONSTANT_DYNAMIC",
"CONSTANT_FIELDREF",
"CONSTANT_FLOAT",
"CONSTANT_INTEGER",
"CONSTANT_INTFMETHODREF",
"CONSTANT_INVOKEDYNAMIC",
"CONSTANT_LONG",
"CONSTANT_METHODHANDLE",
"CONSTANT_METHODREF",
"CONSTANT_METHODTYPE",
"CONSTANT_MODULE",
"CONSTANT_NAMEANDTYPE",
"CONSTANT_PACKAGE",
"CONSTANT_STRING",
"CONSTANT_UNICODE",
"CONSTANT_UTF8",
))
}
}
17 changes: 17 additions & 0 deletions tests/pos/t12396/A_1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// test: -jvm 21+

public class A_1 {
public int f(Object s) {
switch(s) {
case Res.R -> {
return 1;
}
default -> {
return 3;
}
}
}
static enum Res {
R
}
}
5 changes: 5 additions & 0 deletions tests/pos/t12396/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// test: -jvm 21+

class B {
def bar = (new A_1).f(null)
}

0 comments on commit 7a5cb6e

Please sign in to comment.