Skip to content

runtime reflection: corruption in unpickling when pickled data is chunked #7556

Description

@scabug
% head sandbox/mega-trait.scala # attached
trait MegaTrait {
def method0: Int = 0
def method1: Int = 0
def method2: Int = 0
def method3: Int = 0
def method4: Int = 0
def method5: Int = 0
def method6: Int = 0
def method7: Int = 0
def method8: Int = 0
  ~/code/scala tail sandbox/mega-trait.scala
def method2991: Int = 0
def method2992: Int = 0
def method2993: Int = 0
def method2994: Int = 0
def method2995: Int = 0
def method2996: Int = 0
def method2997: Int = 0
def method2998: Int = 0
def method2999: Int = 0
}

% qbin/scalac -d sandbox/ sandbox/mega-trait.scala &&  qbin/scala -nc -classpath sandbox/ -e 'scala.reflect.runtime.universe.typeTag[MegaTrait].tpe.members'java.lang.ArrayIndexOutOfBoundsException: 958737694
	at scala.reflect.internal.pickling.PickleBuffer.readByte(PickleBuffer.scala:104)
	at scala.reflect.internal.pickling.PickleBuffer$$anonfun$createIndex$1.apply$mcVI$sp(PickleBuffer.scala:181)
	at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:149)
	at scala.reflect.internal.pickling.PickleBuffer.createIndex(PickleBuffer.scala:179)
	at scala.reflect.internal.pickling.UnPickler$Scan.<init>(UnPickler.scala:60)
	at scala.reflect.internal.pickling.UnPickler.unpickle(UnPickler.scala:38)
	at scala.reflect.runtime.JavaMirrors$JavaMirror.unpickleClass(JavaMirrors.scala:592)
	at scala.reflect.runtime.SymbolLoaders$TopClassCompleter$$anonfun$complete$1.apply$mcV$sp(SymbolLoaders.scala:35)
	at scala.reflect.runtime.SymbolLoaders$TopClassCompleter$$anonfun$complete$1.apply(SymbolLoaders.scala:32)
	at scala.reflect.runtime.SymbolLoaders$TopClassCompleter$$anonfun$complete$1.apply(SymbolLoaders.scala:32)
	at scala.reflect.internal.SymbolTable.enteringPhaseNotLaterThan(SymbolTable.scala:226)
	at scala.reflect.runtime.SymbolLoaders$TopClassCompleter.complete(SymbolLoaders.scala:32)
	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1319)
	at scala.reflect.internal.Types$TypeRef.thisInfo(Types.scala:2321)
	at scala.reflect.internal.Types$TypeRef.baseClasses(Types.scala:2326)
	at scala.reflect.internal.Types$Type.scala$reflect$internal$Types$Type$$findMembersInternal$1(Types.scala:990)
	at scala.reflect.internal.Types$Type.findMembers(Types.scala:1036)
	at scala.reflect.internal.Types$Type.membersBasedOnFlags(Types.scala:624)
	at scala.reflect.internal.Types$Type.members(Types.scala:577)
	at scala.reflect.internal.Types$Type.members(Types.scala:256)
	at Main$$anon$1.<init>(scalacmd6150594393612715057.scala:1)
	at Main$.main(scalacmd6150594393612715057.scala:1)
	at Main.main(scalacmd6150594393612715057.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:68)
	at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
	at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:99)
	at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:68)
	at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:99)
	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
	at scala.tools.nsc.ScriptRunner.scala$tools$nsc$ScriptRunner$$runCompiled(ScriptRunner.scala:158)
	at scala.tools.nsc.ScriptRunner$$anonfun$runCommand$1.apply(ScriptRunner.scala:205)
	at scala.tools.nsc.ScriptRunner$$anonfun$runCommand$1.apply(ScriptRunner.scala:205)
	at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1$$anonfun$apply$mcZ$sp$1.apply(ScriptRunner.scala:144)
	at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1$$anonfun$apply$mcZ$sp$1.apply(ScriptRunner.scala:144)
	at scala.Option.exists(Option.scala:228)
	at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply$mcZ$sp(ScriptRunner.scala:144)
	at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:118)
	at scala.tools.nsc.ScriptRunner$$anonfun$withCompiledScript$1.apply(ScriptRunner.scala:118)
	at scala.tools.nsc.util.package$.trackingThreads(package.scala:46)
	at scala.tools.nsc.util.package$.waitingForThreads(package.scala:30)
	at scala.tools.nsc.ScriptRunner.withCompiledScript(ScriptRunner.scala:117)
	at scala.tools.nsc.ScriptRunner.runCommand(ScriptRunner.scala:205)
	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:92)
	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
java.lang.RuntimeException: error reading Scala signature of MegaTrait: 958737694
	at scala.reflect.internal.pickling.UnPickler.unpickle(UnPickler.scala:46)
	at scala.reflect.runtime.JavaMirrors$JavaMirror.unpickleClass(JavaMirrors.scala:592)

During unpickling, the var readIndex is mutated thusly:

// (old, new)
(57432,57433)
(57433,57434)
(57434,57435)
(57435,57436)
(57436,57437)
(57437,958737694)

From JavaMirrors

            loadBytes[Array[String]]("scala.reflect.ScalaLongSignature") match {
              case Some(slsig) =>
                info(s"unpickling Scala $clazz and $module with long Scala signature")
                val byteSegments = slsig map (_.getBytes)
                val lens = byteSegments map ByteCodecs.decode
                val bytes = Array.ofDim[Byte](lens.sum)
                var len = 0
                for ((bs, l) <- byteSegments zip lens) {
                  bs.copyToArray(bytes, len, l)
                  len += l
                }
                unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName)
              case None =>
                // class does not have a Scala signature; it's a Java class
                info("translating reflection info for Java " + jclazz) //debug
                initClassAndModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz))
            }

We get the corruption just over the boundary between the two byteSegments.

byteSegments = {byte[2][]@5299}
[0] = {byte[65515]@5315}
[1] = {byte[1864]@5316}

len = {scala.runtime.IntRef@5302}"58957"
lens = {int[2]@5300}
[0] = 57326
[1] = 1631

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions