You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by "Olabusayo Kilo (Jira)" <ji...@apache.org> on 2026/08/13 15:51:00 UTC
[jira] [Updated] (DAFFODIL-3094) Failure when prefix separator is not backtracked after repeating complex element stops
[ https://issues.apache.org/jira/browse/DAFFODIL-3094?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Olabusayo Kilo updated DAFFODIL-3094:
-------------------------------------
Summary: Failure when prefix separator is not backtracked after repeating complex element stops (was: Failure when prefix separator is not backtracked after repeating complex element ends)
> Failure when prefix separator is not backtracked after repeating complex element stops
> --------------------------------------------------------------------------------------
>
> Key: DAFFODIL-3094
> URL: https://issues.apache.org/jira/browse/DAFFODIL-3094
> Project: Daffodil
> Issue Type: Bug
> Affects Versions: 4.2.0
> Reporter: Olabusayo Kilo
> Priority: Major
> Fix For: 4.3.0
>
> Attachments: data.dat, test.xsd
>
>
> Schema:
> {code:xml}
> <xs:element name="r">
> <xs:complexType>
> <xs:sequence dfdl:separatorPosition="prefix" dfdl:separator="/ %NL;/" dfdl:terminator="%NL;">
> <xs:element name="foo" type="xs:string"/>
> <xs:element name="GroupOfFields" maxOccurs="5" dfdl:occursCountKind="implicit">
> <xs:complexType>
> <xs:sequence dfdl:separator="/ %NL;/" dfdl:separatorSuppressionPolicy="never">
> <xs:element name="c">
> <xs:complexType>
> <xs:choice>
> <xs:element name="bar" type="xs:string" dfdl:initiator="R:"/>
> <xs:element name="ban" type="xs:string" dfdl:initiator="N:"/>
> </xs:choice>
> </xs:complexType>
> </xs:element>
> </xs:sequence>
> </xs:complexType>
> </xs:element>
> <xs:element name="baz" type="xs:string" minOccurs="0" />
> </xs:sequence>
> </xs:complexType>
> </xs:element>
> {code}
> Data:
> {code:none}
> /1/N:ABC/R:DEF/N:HIJ/R:LMN/2
> {code}
> In the above, an outer sequence is separatorPosition="prefix" and a complex element, GroupOfFields, has occursCountKind="implicit", minOccurs=1 and maxOccurs=5, and the data has exactly 4 real GroupOfFields occurrences (ABC/DEF/HIJ/LMN) followed by /2; that trailing / belongs to baz's own prefix separator, and 2 is baz's value.
>
> Bug: since maxOccurs=5 and only 4 occurred, the parser must speculatively attempt occurrence #5 (position 5 = maxRepeats, so RequiredOptionalStatus.Optional). It:
> 1. Parses the prefix separator / before slot 5 and succeeds (bits 208→216).
> 2. Tries the child (GroupOfFields's inner choice bar/ban) and both initiators fail, 0 bits consumed (isZL=true).
>
> That failure goes through anyTypeElementFailedParseAttemptStatus (SequenceChildParseResultHelper.scala:190-218):
> {code:scala}
> case _: RequiredOptionalStatus.Optional if isZL => ParseAttemptStatus.AbsentRep
> {code}
> AbsentRep is documented as "backtrack any elements created but retain bit position" which is exactly what parseOneInstanceWithMaybePoU does (SequenceParserBases.scala:413-421): it resets to the PoU (undoing the infoset side effects) but then explicitly forces the bit position back forward past the separator (pstate.dataInputStream.setBitPos0b(currentPos)), i.e. it keeps the separator consumed.
>
> That convention is correct for a simple type whose legitimate empty representation is genuinely zero-length (classic "two adjacent separators = an empty positional slot" idiom). But here the child is a complex type wrapping a mandatory xs:choice with two required initiators; there is no such thing as a valid zero-length match for it. The ZL failure isn't "the slot is legitimately empty," it's "there is no occurrence 5 at all." Keeping the separator steals the / that rightfully belongs to baz's own prefix separator, so baz's separator search then fails, and ultimately the sequence terminator search fails too.
> anyTypeElementFailedParseAttemptStatus conflates two different situations under one AbsentRep result: "legitimately empty content" vs. "total structural failure with nothing consumed"; only the former should retain the separator. The complex-type/model-group path currently has no static "can this ever legitimately be zero-length" flag analogous to isEmptyRepZeroLength (which simple types have) or isModelGroupRepPossiblyZeroLength (which exists for model groups used directly as sequence children, but isn't threaded into element-with-complex-type result helpers).
>
> This is a real design gap the code needs a way to know, for a complex-typed array element, whether its content can ever be validly zero-length, and use that to decide AbsentRep (retain separator) vs. a status that forces full backtrack (give the separator back).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)