Scala Programming Language
  1. Scala Programming Language
  2. SI-5374

Deserialization of ListBuffer results in a non-mutable structure prone to throwing NoSuchElementException

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: Scala 2.9.1
    • Fix Version/s: Scala 2.10.0-M1
    • Component/s: Collections
    • Labels:
    • Environment:

      Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26).

      Description

      Something is amiss with deserialization of ListBuffer, as shown here:

      import collection.mutable.ListBuffer
      import java.io._
      val baos = new ByteArrayOutputStream
      val oos = new ObjectOutputStream(baos)
      oos.writeObject( ListBuffer(1,2,3) )
      val bais = new ByteArrayInputStream( baos.toByteArray )
      val ois = new ObjectInputStream(bais)
      val lb = ois.readObject.asInstanceOf[ListBuffer[Int]]
      val lb2 = ListBuffer[Int]() ++= lb
      lb2 ++= List(1)  // All okay
      lb ++= List(1)  // Throws an exception for me
      

      Not sure whether this is related to other deserialization bugs (e.g. #SI-5262).

        Issue Links

          Activity

          Hide
          Jed Wesley-Smith added a comment - - edited

          From what I can tell the last0 field isn't being deserialized correctly. As the :: has custom deserialization (see ::.readResolve) when the ListBuffer is deserialized it holds the old last0 reference, but it needs to be updated to the correct one in start chain. This hypotheses is supported by the fact that length is indeed increased as expected.

          OT but interesting, the code above does indeed throw an exception in the REPL, but not when compiled by SBT.

          Also, verified that prepending does work.

          Show
          Jed Wesley-Smith added a comment - - edited From what I can tell the last0 field isn't being deserialized correctly. As the :: has custom deserialization (see ::.readResolve) when the ListBuffer is deserialized it holds the old last0 reference, but it needs to be updated to the correct one in start chain. This hypotheses is supported by the fact that length is indeed increased as expected. OT but interesting, the code above does indeed throw an exception in the REPL, but not when compiled by SBT. Also, verified that prepending does work.
          Hide
          Jed Wesley-Smith added a comment -
          Show
          Jed Wesley-Smith added a comment - Originally a StackOverflow question
          Hide
          Aleksandar Prokopec added a comment -

          This is indeed due to list serialization. With the current implementation there, any object that is serialized and which has multiple fields with references into the same list will be inaccurately deserialized. While we could patch list buffers to fix this, a better solution would be to change the way lists are serialized, and avoid surprising behaviour in the future.

          Show
          Aleksandar Prokopec added a comment - This is indeed due to list serialization. With the current implementation there, any object that is serialized and which has multiple fields with references into the same list will be inaccurately deserialized. While we could patch list buffers to fix this, a better solution would be to change the way lists are serialized, and avoid surprising behaviour in the future.

            People

            • Assignee:
              Aleksandar Prokopec
              Reporter:
              Rex Kerr
            • Votes:
              0 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development