From e234978dfddf5f4871312eb7744ac3b133ad00da Mon Sep 17 00:00:00 2001 From: aleksandar Date: Wed, 25 Jan 2012 20:17:52 +0100 Subject: Refine fix for SI-5374 - make list deserialization backward-compatible. This is done by structurally serializing list nodes, but prepending a special `ListSerializationStart` symbol ahead of the list. If this symbol is not in the object input stream, the deserialization reverts to the old mode. Note there is not much to be done for list buffers - their serialization was broken before, so legacy serialized list buffers are no longer deserializable. However, their serialVersionUID was changed to reflect this, so deserializing a legacy list buffer should fail fast. --- test/files/run/si5374.check | 5 ++++- test/files/run/si5374.scala | 52 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 10 deletions(-) (limited to 'test/files') diff --git a/test/files/run/si5374.check b/test/files/run/si5374.check index cdf0bc7e5b..6be88d77ec 100644 --- a/test/files/run/si5374.check +++ b/test/files/run/si5374.check @@ -1,3 +1,6 @@ ListBuffer(1, 2, 3, 1) ListBuffer(1, 2, 3, 1) -ListBuffer() \ No newline at end of file +ListBuffer() +List(1, 2, 3, 4, 5) +List(1, 2, 3) +ok \ No newline at end of file diff --git a/test/files/run/si5374.scala b/test/files/run/si5374.scala index a5678c3a81..9b1671e795 100644 --- a/test/files/run/si5374.scala +++ b/test/files/run/si5374.scala @@ -11,15 +11,22 @@ object Test { def main(args: Array[String]) { ticketExample() emptyListBuffer() + list() + legacyList() + objectWithMultipleLists() } - def ticketExample() { + def inAndOut[T <: AnyRef](obj: T): T = { val baos = new ByteArrayOutputStream val oos = new ObjectOutputStream(baos) - oos.writeObject( ListBuffer(1,2,3) ) + oos.writeObject( obj ) val bais = new ByteArrayInputStream( baos.toByteArray ) val ois = new ObjectInputStream(bais) - val lb = ois.readObject.asInstanceOf[ListBuffer[Int]] + ois.readObject.asInstanceOf[T] + } + + def ticketExample() { + val lb = inAndOut(ListBuffer(1, 2, 3)) val lb2 = ListBuffer[Int]() ++= lb lb2 ++= List(1) @@ -29,14 +36,41 @@ object Test { } def emptyListBuffer() { - val baos = new ByteArrayOutputStream - val oos = new ObjectOutputStream(baos) - oos.writeObject( ListBuffer() ) - val bais = new ByteArrayInputStream( baos.toByteArray ) - val ois = new ObjectInputStream(bais) - val lb = ois.readObject.asInstanceOf[ListBuffer[Int]] + val lb = inAndOut(ListBuffer[Int]()) println(lb) } + def list() { + val l = inAndOut(List(1, 2, 3, 4, 5)) + + println(l) + } + + // this byte array corresponds to what List(1, 2, 3) used to be serialized to prior to this fix + val listBytes = Array[Byte](-84, -19, 0, 5, 115, 114, 0, 39, 115, 99, 97, 108, 97, 46, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 46, 105, 109, 109, 117, 116, 97, 98, 108, 101, 46, 36, 99, 111, 108, 111, 110, 36, 99, 111, 108, 111, 110, -118, 92, 99, 91, -10, -40, -7, 109, 3, 0, 2, 76, 0, 43, 115, 99, 97, 108, 97, 36, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 36, 105, 109, 109, 117, 116, 97, 98, 108, 101, 36, 36, 99, 111, 108, 111, 110, 36, 99, 111, 108, 111, 110, 36, 36, 104, 100, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 76, 0, 2, 116, 108, 116, 0, 33, 76, 115, 99, 97, 108, 97, 47, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 47, 105, 109, 109, 117, 116, 97, 98, 108, 101, 47, 76, 105, 115, 116, 59, 120, 112, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 0, 1, 115, 113, 0, 126, 0, 4, 0, 0, 0, 2, 115, 113, 0, 126, 0, 4, 0, 0, 0, 3, 115, 114, 0, 44, 115, 99, 97, 108, 97, 46, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 46, 105, 109, 109, 117, 116, 97, 98, 108, 101, 46, 76, 105, 115, 116, 83, 101, 114, 105, 97, 108, 105, 122, 101, 69, 110, 100, 36, -118, 92, 99, 91, -9, 83, 11, 109, 2, 0, 0, 120, 112, 120) + + def legacyList() { + val bais = new ByteArrayInputStream(listBytes) + val ois = new ObjectInputStream(bais) + val l = ois.readObject() + + println(l) + } + + class Foo extends Serializable { + val head = List(1, 2, 3) + val last = head.tail.tail + def structuralSharing: Boolean = head.tail.tail eq last + + assert(structuralSharing) + } + + def objectWithMultipleLists() { + val foo = inAndOut(new Foo) + + if (foo.structuralSharing) println("ok") + else println("no structural sharing") + } + } -- cgit v1.2.3