You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ja...@apache.org on 2022/02/15 20:02:12 UTC

[daffodil] branch main updated: Call setFinished on the correct data output stream

This is an automated email from the ASF dual-hosted git repository.

jadams pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git


The following commit(s) were added to refs/heads/main by this push:
     new 9b8065a  Call setFinished on the correct data output stream
9b8065a is described below

commit 9b8065a893fe13e56397f7ddcc58dfe8441e28d9
Author: Josh Adams <ja...@owlcyberdefense.com>
AuthorDate: Mon Feb 14 17:51:20 2022 -0500

    Call setFinished on the correct data output stream
    
    When splitting the data output stream during unparse for a bitOrder
    change, we had been setting the incorrect DOS to finished. We need to
    call dos.setFinished(UState) before we update the UState's
    dataOutputStream to the new split DOS.
    
    DAFFODIL-2653
---
 .../daffodil/processors/unparsers/UState.scala      | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
index c701f3f..7d2008d 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
@@ -327,8 +327,6 @@ abstract class UState(
     }
     if (isSplitNeeded) {
       Assert.invariant(dos.isBuffering) // Direct DOS always has absolute position, so has to be buffering.
-      val newDOS = dos.addBuffered
-      dataOutputStream = newDOS
       //
       // Just splitting to start a new bitOrder on a byte boundary in a new
       // buffered DOS
@@ -344,7 +342,24 @@ abstract class UState(
       // Finished means you won't add data to the end of it any more.
       // It does NOT prevent information like the absoluteBitPos to
       // propagate.
-      dos.setFinished(this)
+      //
+      // When setFinished is called the DOS is going to store the state that we
+      // pass into it in finishedFormatInfo. Eventually this DOS will become a
+      // direct DOS that may be delivered to a following buffered DOS. When that
+      // happens this saved finishedFormatInfo will be used. However, this
+      // requires that the UState does not change while we are waiting for this
+      // DOS to become direct. If the state does change, it will become
+      // incorrect and can lead to undefined behavior. To prevent this, we must
+      // clone the UState so it can no longer change, and pass that clone into
+      // setFinished.
+      val finfo = this match {
+        case m: UStateMain => m.cloneForSuspension(dos)
+        case _ => Assert.invariantFailed("State must be a UStateMain when splitting for bit order change")
+      }
+
+      val newDOS = dos.addBuffered
+      dataOutputStream = newDOS
+      dos.setFinished(finfo)
     }
   }