Skip to content

Commit 259eddf

Browse files
committed
Add jvm backend check for UTF-8 Constant length
1 parent 5c628d9 commit 259eddf

File tree

8 files changed

+69
-2
lines changed

8 files changed

+69
-2
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ class Compiler {
142142
new sjs.JUnitBootstrappers, // Generate JUnit-specific bootstrapper classes for Scala.js (not enabled by default)
143143
new CollectEntryPoints, // Collect all entry points and save them in the context
144144
new CollectSuperCalls, // Find classes that are called with super
145-
new RepeatableAnnotations) :: // Aggregate repeatable annotations
145+
new RepeatableAnnotations, // Aggregate repeatable annotations
146+
new CheckJVMSpecification) :: // Checks related to the JVM Specification before code generation
146147
Nil
147148

148149
/** Generate the output of the compilation */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import MegaPhase.MiniPhase
5+
import GenericSignatures.*
6+
import core.Contexts.*
7+
import core.Decorators.*
8+
import core.Constants.*
9+
import core.Symbols.*
10+
import util.SrcPos
11+
12+
final class CheckJVMSpecification extends MiniPhase:
13+
import ast.tpd.*
14+
15+
override def phaseName: String = CheckJVMSpecification.name
16+
override def description: String = CheckJVMSpecification.description
17+
18+
19+
override def transformDefDef(tree: DefDef)(using Context): Tree =
20+
val sym = tree.symbol
21+
val memberTpe = atPhase(ctx.base.erasurePhase) { sym.owner.denot.thisType.memberInfo(sym) }
22+
for sig <- GenericSignatures.javaSig(sym, memberTpe) do
23+
checkUTF8MaximumLength(sig, tree.srcPos, prefix = "Method signature")
24+
tree
25+
26+
override def transformLiteral(tree: Literal)(using Context): Tree =
27+
val Literal(cste) = tree
28+
if cste.tpe == defn.StringType then
29+
checkUTF8MaximumLength(cste.stringValue, tree.srcPos.focus, prefix = "String")
30+
tree
31+
32+
/** See https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.7 */
33+
private def checkUTF8MaximumLength(str: String, pos: SrcPos, prefix: String)(using Context) =
34+
val UTF8_MAX_LENGTH = 65535
35+
if str.length > UTF8_MAX_LENGTH then
36+
report.error(em"""${prefix} length exceed the maximum length allowed by the JVM specification.
37+
|Allowed: ${UTF8_MAX_LENGTH}
38+
|Actual : ${str.length}""", pos)
39+
40+
object CheckJVMSpecification:
41+
val name = "checkJVMspec"
42+
val description = "check issues related to the jvm specification"
43+

tests/neg/i15850-a.check

+6
Large diffs are not rendered by default.

tests/neg/i15850-a.scala

+1
Large diffs are not rendered by default.

tests/neg/i15850-b.check

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- Error: tests/neg/i15850-b.scala:9:4 ---------------------------------------------------------------------------------
2+
9 |def crash(x: Level7): Unit = () // error
3+
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
|Method signature length exceed the maximum length allowed by the JVM specification.
5+
|Allowed: 65535
6+
|Actual : 496979

tests/neg/i15850-b.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
type Level1 = Tuple4[Unit, Unit, Unit, Unit]
2+
type Level2 = Tuple4[Level1, Level1, Level1, Level1]
3+
type Level3 = Tuple4[Level2, Level2, Level2, Level2]
4+
type Level4 = Tuple4[Level3, Level3, Level3, Level3]
5+
type Level5 = Tuple4[Level4, Level4, Level4, Level4]
6+
type Level6 = Tuple4[Level5, Level5, Level5, Level5]
7+
type Level7 = Tuple4[Level6, Level6, Level6, Level6]
8+
9+
def crash(x: Level7): Unit = () // error

tests/pos/i15850.scala

+1
Large diffs are not rendered by default.

tests/printing/transformed/lazy-vals-new.check

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[[syntax trees at end of MegaPhase{dropOuterAccessors, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}]] // tests/printing/transformed/lazy-vals-new.scala
1+
[[syntax trees at end of MegaPhase{dropOuterAccessors, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations, checkJVMspec}]] // tests/printing/transformed/lazy-vals-new.scala
22
package <empty> {
33
@SourceFile("tests/printing/transformed/lazy-vals-new.scala") final module
44
class A extends Object {

0 commit comments

Comments
 (0)