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)
}
}