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"),

Reply via email to