This is an automated email from the ASF dual-hosted git repository.
slawrence pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git
The following commit(s) were added to refs/heads/master by this push:
new fb73683 Fix abort when viewing prefixed length elements in the
debugger
fb73683 is described below
commit fb736835446f89d81057e50f30d9a8a3087f4538
Author: Steve Lawrence <[email protected]>
AuthorDate: Mon Dec 14 12:29:00 2020 -0500
Fix abort when viewing prefixed length elements in the debugger
The InfosetWalker, which is used for displaying the infoset, expects
elements to have a container element. When creating a detached element
for prefixed elements, we did so without a DIDocument. This causes
assertions to fail or null pointers to be hit. To ensure the detached
element used for prefixed parsing/element is appropriate the
InfosetWalker, create a "detached" DIDocument and the new detached
DIElement to that.
DAFFODIL-2348
---
.../org/apache/daffodil/CLI/input/prefix.txt | 1 +
.../apache/daffodil/CLI/prefixed_length.dfdl.xsd | 41 ++++++++++++++++++++++
.../apache/daffodil/debugger/TestCLIDebugger.scala | 30 ++++++++++++++++
.../unparsers/SpecifiedLengthUnparsers.scala | 14 +++++---
.../org/apache/daffodil/infoset/InfosetImpl.scala | 14 ++++++++
.../processors/parsers/BinaryNumberTraits.scala | 8 +++--
project/Rat.scala | 1 +
7 files changed, 102 insertions(+), 7 deletions(-)
diff --git
a/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/prefix.txt
b/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/prefix.txt
new file mode 100644
index 0000000..df97d29
--- /dev/null
+++ b/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/prefix.txt
@@ -0,0 +1 @@
+04abcd
diff --git
a/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/prefixed_length.dfdl.xsd
b/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/prefixed_length.dfdl.xsd
new file mode 100644
index 0000000..f778689
--- /dev/null
+++
b/daffodil-cli/src/it/resources/org/apache/daffodil/CLI/prefixed_length.dfdl.xsd
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/">
+
+ <xs:include
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/" >
+ <dfdl:format ref="GeneralFormat"
+ lengthKind="explicit"
+ lengthUnits="bytes" />
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:simpleType name="prefix" dfdl:length="2">
+ <xs:restriction base="xs:int" />
+ </xs:simpleType>
+
+ <xs:element name="field" type="xs:string"
+ dfdl:lengthKind="prefixed" dfdl:prefixLengthType="prefix"
dfdl:prefixIncludesPrefixLength="no"
+ dfdl:terminator="%NL;" />
+
+</xs:schema>
diff --git
a/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
b/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
index 394e77b..b1c8da0 100644
---
a/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
+++
b/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
@@ -1127,4 +1127,34 @@ class TestCLIdebugger {
}
}*/
+ @Test def test_3585_CLI_Debugger_prefixLength(): Unit = {
+ val schemaFile =
Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/prefixed_length.dfdl.xsd")
+ val inputFile =
Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/prefix.txt")
+ val (testSchemaFile, testInputFile) = if (Util.isWindows)
(Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile,
inputFile)
+
+ val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS)
else Util.start("")
+
+ try {
+ val cmd = String.format("%s -d parse -s %s %s", Util.binPath,
testSchemaFile, testInputFile)
+ shell.sendLine(cmd)
+ shell.expect(contains("(debug)"))
+ shell.sendLine("display info infoset")
+ shell.expect(contains("(debug)"))
+ shell.sendLine("display eval .")
+ shell.sendLine("step")
+ shell.expect(contains("<field></field>"))
+ shell.sendLine("step")
+ shell.expect(contains("<field (prefixLength)></field (prefixLength)>"))
+ shell.sendLine("step")
+ shell.expect(contains("<field (prefixLength)>4</field (prefixLength)>"))
+ shell.sendLine("step")
+ shell.expect(contains("<field>abcd</field>"))
+ shell.sendLine("complete")
+ shell.expect(contains("<field>abcd</field>"))
+ } finally {
+ shell.close()
+ }
+ }
+
+
}
diff --git
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala
index 8410dcc..958f6b7 100644
---
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala
+++
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLengthUnparsers.scala
@@ -328,9 +328,12 @@ trait KnownPrefixedLengthUnparserMixin {
bits
}
val adjustedLenInUnits = lenInUnits + prefixedLengthAdjustmentInUnits
+ // Create a "detached" DIDocument with a single child element that the
+ // prefix length will be unparsed from. This creates a completely new
+ // infoset and unparses from that, so care is taken to ensure this infoset
+ // is only used for the prefix length unparsing and is removed afterwards
+ val plElement = Infoset.newDetachedElement(state,
prefixedLengthERD).asInstanceOf[DISimple]
- // create a "detached" element that the prefix length will be parsed to.
- val plElement =
Infoset.newElement(prefixedLengthERD).asInstanceOf[DISimple]
plElement.setDataValue(java.lang.Integer.valueOf(adjustedLenInUnits.toInt))
// unparse the prefixed length element
@@ -385,8 +388,11 @@ class SpecifiedLengthPrefixedUnparser(
override lazy val childProcessors = Vector(prefixedLengthUnparser, eUnparser)
override def unparse(state: UState): Unit = {
- // create a "detached" element that the prefix length will be used to
unparse
- val plElem = Infoset.newElement(prefixedLengthERD).asInstanceOf[DISimple]
+ // Create a "detached" DIDocument with a single child element that the
+ // prefix length will be parsed to. This creates a completely new
+ // infoset and parses to that, so care is taken to ensure this infoset
+ // is only used for the prefix length parsing and is removed afterwards
+ val plElem = Infoset.newDetachedElement(state,
prefixedLengthERD).asInstanceOf[DISimple]
// The prefixedLengthUnparser is going to end up creating a suspension
// because plElem does not have a value yet. We will temporary push the
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
index 4d7e816..d3cebf3 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
@@ -1782,4 +1782,18 @@ object Infoset {
new DIDocument(erd)
}
+ /**
+ * Create a new detached infoset with a single specified element. This
+ * essentially creates another infoset with a completely differed DIDocument
+ * so care should be taken to ensure things like expressions are not evaluated
+ * or new elements are not added within the scope of this infoset, as it will
+ * have no access to the true infoset. It is up to the caller to ensure the
+ * return infoset element is used safely
+ */
+ def newDetachedElement(state: ParseOrUnparseState, erd: ElementRuntimeData):
InfosetElement = {
+ val detachedDoc = Infoset.newDocument(erd).asInstanceOf[DIDocument]
+ val detachedElem = Infoset.newElement(erd)
+ detachedDoc.addChild(detachedElem, state.tunable)
+ detachedElem
+ }
}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala
index e58d22d..83c99e3 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/BinaryNumberTraits.scala
@@ -72,9 +72,11 @@ trait PrefixedLengthParserMixin {
def getPrefixedLengthInUnits(state: PState): Long = {
val savedInfoset = state.infoset
- // create a "detached" element that the prefix length will be parsed to.
- // This temporarily removes to infoset.
- val plElement =
Infoset.newElement(prefixedLengthERD).asInstanceOf[DISimple]
+ // Create a "detached" document with a single child element that the prefix
+ // length will be parsed to. This creates a completely new infoset and
+ // parses to that, so care is taken to ensure we reset it back after the
parse
+ val plElement = Infoset.newDetachedElement(state,
prefixedLengthERD).asInstanceOf[DISimple]
+
state.infoset = plElement
val parsedLen: JLong = try {
diff --git a/project/Rat.scala b/project/Rat.scala
index 2489a69..4c56afb 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -73,6 +73,7 @@ object Rat {
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input18.txt"),
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input19.txt"),
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/inputBig1M.txt"),
+
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/prefix.txt"),
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/test_DFDL-714.txt"),
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/output/output1.txt"),
file("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/output/output1_nopretty.txt"),