diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala index 959d97e337..92348ee819 100644 --- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala +++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/DaffodilCCodeGenerator.scala @@ -278,7 +278,7 @@ object DaffodilCCodeGenerator case g: BinaryDouble => binaryFloatGenerateCode(g.e, lengthInBits = 64, cgState) case g: BinaryFloat => binaryFloatGenerateCode(g.e, lengthInBits = 32, cgState) case g: BinaryIntegerKnownLength => - binaryIntegerKnownLengthGenerateCode(g.e, g.lengthInBits, g.signed, cgState) + binaryIntegerKnownLengthGenerateCode(g.e, g.lengthInBits, cgState) case g: CaptureContentLengthEnd => noop(g) case g: CaptureContentLengthStart => noop(g) case g: CaptureValueLengthEnd => noop(g) diff --git a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryIntegerKnownLengthCodeGenerator.scala b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryIntegerKnownLengthCodeGenerator.scala index 4a835c9ac4..1d2476cb3d 100644 --- a/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryIntegerKnownLengthCodeGenerator.scala +++ b/daffodil-codegen-c/src/main/scala/org/apache/daffodil/codegen/c/generators/BinaryIntegerKnownLengthCodeGenerator.scala @@ -18,6 +18,7 @@ package org.apache.daffodil.codegen.c.generators import org.apache.daffodil.core.dsom.ElementBase +import org.apache.daffodil.runtime1.dpath.NodeInfo.PrimType.PrimNumeric trait BinaryIntegerKnownLengthCodeGenerator extends BinaryValueCodeGenerator { @@ -25,7 +26,6 @@ trait BinaryIntegerKnownLengthCodeGenerator extends BinaryValueCodeGenerator { def binaryIntegerKnownLengthGenerateCode( e: ElementBase, lengthInBits: Long, - signed: Boolean, cgState: CodeGeneratorState ): Unit = { val cLengthInBits = lengthInBits match { @@ -35,6 +35,7 @@ trait BinaryIntegerKnownLengthCodeGenerator extends BinaryValueCodeGenerator { case n if n <= 64 => 64 case _ => e.SDE("Binary integer lengths longer than 64 bits are not supported.") } + val signed = e.primType.asInstanceOf[PrimNumeric].isSigned val primType = if (signed) s"int$cLengthInBits" else s"uint$cLengthInBits" val addField = valueAddField(e, lengthInBits, primType, _, cgState) val validateFixed = valueValidateFixed(e, _, cgState) diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala index 3992415bcd..825f69da83 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala @@ -774,11 +774,37 @@ trait ElementBase if ( result.isDefined && repElement.isSimpleType && representation == Representation.Binary ) { + val nBits = result.get primType match { case primNumeric: NodeInfo.PrimType.PrimNumeric => - if (primNumeric.width.isDefined) { - val nBits = result.get - val width = primNumeric.width.get + if (primNumeric.minWidth.isDefined) { + val minWidth = primNumeric.minWidth.get + if (nBits < minWidth) { + val isSigned = primNumeric.isSigned + val signedStr = if (isSigned) "a signed" else "an unsigned" + val outOfRangeFmtStr = + "Minimum length for %s binary integer is %d bit(s), number of bits %d out of range. " + + "An unsigned integer with length 1 bit could be used instead." + if (isSigned && tunable.allowSignedIntegerLength1Bit && nBits == 1) { + SDW( + WarnID.SignedBinaryIntegerLength1Bit, + outOfRangeFmtStr, + signedStr, + minWidth, + nBits + ) + } else { + SDE( + outOfRangeFmtStr, + signedStr, + minWidth, + nBits + ) + } + } + } + if (primNumeric.maxWidth.isDefined) { + val width = primNumeric.maxWidth.get if (nBits > width) { SDE( "Number of bits %d out of range for binary %s, must be between 1 and %d bits.", diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala index f9982d71a4..12b53c352a 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala @@ -786,7 +786,7 @@ trait ElementBaseGrammarMixin ) { ConvertZonedCombinator( this, - new IBM4690PackedIntegerKnownLength(this, false, binaryNumberKnownLengthInBits), + new IBM4690PackedIntegerKnownLength(this, binaryNumberKnownLengthInBits), textConverter ) } @@ -796,7 +796,7 @@ trait ElementBaseGrammarMixin ) { ConvertZonedCombinator( this, - new IBM4690PackedIntegerRuntimeLength(this, false), + new IBM4690PackedIntegerRuntimeLength(this), textConverter ) } @@ -806,7 +806,7 @@ trait ElementBaseGrammarMixin ) { ConvertZonedCombinator( this, - new IBM4690PackedIntegerDelimitedEndOfData(this, false), + new IBM4690PackedIntegerDelimitedEndOfData(this), textConverter ) } @@ -816,7 +816,7 @@ trait ElementBaseGrammarMixin ) { ConvertZonedCombinator( this, - new IBM4690PackedIntegerPrefixedLength(this, false), + new IBM4690PackedIntegerPrefixedLength(this), textConverter ) } @@ -827,7 +827,6 @@ trait ElementBaseGrammarMixin this, new PackedIntegerKnownLength( this, - false, packedSignCodes, binaryNumberKnownLengthInBits ), @@ -838,7 +837,7 @@ trait ElementBaseGrammarMixin prod("packedRuntimeLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Packed) { ConvertZonedCombinator( this, - new PackedIntegerRuntimeLength(this, false, packedSignCodes), + new PackedIntegerRuntimeLength(this, packedSignCodes), textConverter ) } @@ -846,7 +845,7 @@ trait ElementBaseGrammarMixin prod("packedDelimitedLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Packed) { ConvertZonedCombinator( this, - new PackedIntegerDelimitedEndOfData(this, false, packedSignCodes), + new PackedIntegerDelimitedEndOfData(this, packedSignCodes), textConverter ) } @@ -854,7 +853,7 @@ trait ElementBaseGrammarMixin prod("packedPrefixedLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Packed) { ConvertZonedCombinator( this, - new PackedIntegerPrefixedLength(this, false, packedSignCodes), + new PackedIntegerPrefixedLength(this, packedSignCodes), textConverter ) } @@ -897,7 +896,7 @@ trait ElementBaseGrammarMixin private lazy val packedSignCodes = PackedSignCodes(binaryPackedSignCodes, binaryNumberCheckPolicy) - private def binaryIntegerValue(isSigned: Boolean) = { + private lazy val binaryIntegerValue = { // // Is it a single byte or smaller // @@ -910,10 +909,10 @@ trait ElementBaseGrammarMixin } (binaryNumberRep, lengthKind, binaryNumberKnownLengthInBits) match { case (BinaryNumberRep.Binary, LengthKind.Prefixed, _) => - new BinaryIntegerPrefixedLength(this, isSigned) - case (BinaryNumberRep.Binary, _, -1) => new BinaryIntegerRuntimeLength(this, isSigned) + new BinaryIntegerPrefixedLength(this) + case (BinaryNumberRep.Binary, _, -1) => new BinaryIntegerRuntimeLength(this) case (BinaryNumberRep.Binary, _, _) => - new BinaryIntegerKnownLength(this, isSigned, binaryNumberKnownLengthInBits) + new BinaryIntegerKnownLength(this, binaryNumberKnownLengthInBits) case (_, LengthKind.Implicit, _) => SDE("lengthKind='implicit' is not allowed with packed binary formats") case (_, _, _) @@ -923,26 +922,25 @@ trait ElementBaseGrammarMixin binaryNumberKnownLengthInBits ) case (BinaryNumberRep.Packed, LengthKind.Delimited, -1) => - new PackedIntegerDelimitedEndOfData(this, isSigned, packedSignCodes) + new PackedIntegerDelimitedEndOfData(this, packedSignCodes) case (BinaryNumberRep.Packed, LengthKind.Prefixed, -1) => - new PackedIntegerPrefixedLength(this, isSigned, packedSignCodes) + new PackedIntegerPrefixedLength(this, packedSignCodes) case (BinaryNumberRep.Packed, _, -1) => - new PackedIntegerRuntimeLength(this, isSigned, packedSignCodes) + new PackedIntegerRuntimeLength(this, packedSignCodes) case (BinaryNumberRep.Packed, _, _) => new PackedIntegerKnownLength( this, - isSigned, packedSignCodes, binaryNumberKnownLengthInBits ) case (BinaryNumberRep.Ibm4690Packed, LengthKind.Delimited, -1) => - new IBM4690PackedIntegerDelimitedEndOfData(this, isSigned) + new IBM4690PackedIntegerDelimitedEndOfData(this) case (BinaryNumberRep.Ibm4690Packed, LengthKind.Prefixed, -1) => - new IBM4690PackedIntegerPrefixedLength(this, isSigned) + new IBM4690PackedIntegerPrefixedLength(this) case (BinaryNumberRep.Ibm4690Packed, _, -1) => - new IBM4690PackedIntegerRuntimeLength(this, isSigned) + new IBM4690PackedIntegerRuntimeLength(this) case (BinaryNumberRep.Ibm4690Packed, _, _) => - new IBM4690PackedIntegerKnownLength(this, isSigned, binaryNumberKnownLengthInBits) + new IBM4690PackedIntegerKnownLength(this, binaryNumberKnownLengthInBits) case (BinaryNumberRep.Bcd, _, _) => primType match { case PrimType.Long | PrimType.Int | PrimType.Short | PrimType.Byte => @@ -974,13 +972,8 @@ trait ElementBaseGrammarMixin // This is in the spirit of that section. val res: Gram = primType match { - case PrimType.Byte | PrimType.Short | PrimType.Int | PrimType.Long | PrimType.Integer => { - binaryIntegerValue(true) - } - - case PrimType.UnsignedByte | PrimType.UnsignedShort | PrimType.UnsignedInt | - PrimType.UnsignedLong | PrimType.NonNegativeInteger => { - binaryIntegerValue(false) + case n: PrimType.PrimNumeric if n.isInteger => { + binaryIntegerValue } case PrimType.Double | PrimType.Float => { diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala index 2fbcad59e4..8c2b4b5940 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesBinaryNumber.scala @@ -40,37 +40,33 @@ import org.apache.daffodil.unparsers.runtime1.BinaryIntegerKnownLengthUnparser import org.apache.daffodil.unparsers.runtime1.BinaryIntegerPrefixedLengthUnparser import org.apache.daffodil.unparsers.runtime1.BinaryIntegerRuntimeLengthUnparser -class BinaryIntegerRuntimeLength(val e: ElementBase, signed: Boolean) - extends Terminal(e, true) { +class BinaryIntegerRuntimeLength(val e: ElementBase) extends Terminal(e, true) { override lazy val parser = new BinaryIntegerRuntimeLengthParser( e.elementRuntimeData, - signed, e.lengthEv, e.lengthUnits ) override lazy val unparser: Unparser = new BinaryIntegerRuntimeLengthUnparser( e.elementRuntimeData, - signed, e.lengthEv, e.lengthUnits ) } -class BinaryIntegerKnownLength(val e: ElementBase, val signed: Boolean, val lengthInBits: Long) +class BinaryIntegerKnownLength(val e: ElementBase, val lengthInBits: Long) extends Terminal(e, true) { override lazy val parser = { - new BinaryIntegerKnownLengthParser(e.elementRuntimeData, signed, lengthInBits.toInt) + new BinaryIntegerKnownLengthParser(e.elementRuntimeData, lengthInBits.toInt) } override lazy val unparser: Unparser = - new BinaryIntegerKnownLengthUnparser(e.elementRuntimeData, signed, lengthInBits.toInt) + new BinaryIntegerKnownLengthUnparser(e.elementRuntimeData, lengthInBits.toInt) } -class BinaryIntegerPrefixedLength(val e: ElementBase, signed: Boolean) - extends Terminal(e, true) { +class BinaryIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) { private lazy val erd = e.elementRuntimeData private lazy val plerd = e.prefixedLengthElementDecl.elementRuntimeData @@ -81,7 +77,6 @@ class BinaryIntegerPrefixedLength(val e: ElementBase, signed: Boolean) erd, e.prefixedLengthBody.parser, plerd, - signed, e.lengthUnits, pladj ) @@ -101,7 +96,6 @@ class BinaryIntegerPrefixedLength(val e: ElementBase, signed: Boolean) e.prefixedLengthBody.unparser, plerd, maybeNBits, - signed, e.lengthUnits, pladj ) diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala index 152af02cba..a5380474f5 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesIBM4690Packed.scala @@ -33,11 +33,9 @@ import org.apache.daffodil.unparsers.runtime1.IBM4690PackedIntegerKnownLengthUnp import org.apache.daffodil.unparsers.runtime1.IBM4690PackedIntegerPrefixedLengthUnparser import org.apache.daffodil.unparsers.runtime1.IBM4690PackedIntegerRuntimeLengthUnparser -class IBM4690PackedIntegerRuntimeLength(val e: ElementBase, signed: Boolean) - extends Terminal(e, true) { +class IBM4690PackedIntegerRuntimeLength(val e: ElementBase) extends Terminal(e, true) { override lazy val parser = new IBM4690PackedIntegerRuntimeLengthParser( e.elementRuntimeData, - signed, e.lengthEv, e.lengthUnits ) @@ -49,23 +47,21 @@ class IBM4690PackedIntegerRuntimeLength(val e: ElementBase, signed: Boolean) ) } -class IBM4690PackedIntegerKnownLength(val e: ElementBase, signed: Boolean, lengthInBits: Long) +class IBM4690PackedIntegerKnownLength(val e: ElementBase, lengthInBits: Long) extends Terminal(e, true) { override lazy val parser = - new IBM4690PackedIntegerKnownLengthParser(e.elementRuntimeData, signed, lengthInBits.toInt) + new IBM4690PackedIntegerKnownLengthParser(e.elementRuntimeData, lengthInBits.toInt) override lazy val unparser: Unparser = new IBM4690PackedIntegerKnownLengthUnparser(e.elementRuntimeData, lengthInBits.toInt) } -class IBM4690PackedIntegerPrefixedLength(val e: ElementBase, signed: Boolean) - extends Terminal(e, true) { +class IBM4690PackedIntegerPrefixedLength(val e: ElementBase) extends Terminal(e, true) { override lazy val parser = new IBM4690PackedIntegerPrefixedLengthParser( e.elementRuntimeData, e.prefixedLengthBody.parser, e.prefixedLengthElementDecl.elementRuntimeData, - signed, e.lengthUnits, e.prefixedLengthAdjustmentInUnits ) diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala index 9459267ce0..21baad5654 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesLengthKind.scala @@ -205,7 +205,6 @@ case class HexBinaryLengthPrefixed(e: ElementBase) extends Terminal(e, true) { abstract class PackedIntegerDelimited( e: ElementBase, - signed: Boolean, packedSignCodes: PackedSignCodes ) extends StringDelimited(e) { @@ -223,9 +222,8 @@ abstract class PackedIntegerDelimited( case class PackedIntegerDelimitedEndOfData( e: ElementBase, - signed: Boolean, packedSignCodes: PackedSignCodes -) extends PackedIntegerDelimited(e, signed, packedSignCodes) { +) extends PackedIntegerDelimited(e, packedSignCodes) { val isDelimRequired: Boolean = false } @@ -289,8 +287,7 @@ case class BCDDecimalDelimitedEndOfData(e: ElementBase) extends BCDDecimalDelimi val isDelimRequired: Boolean = false } -abstract class IBM4690PackedIntegerDelimited(e: ElementBase, signed: Boolean) - extends StringDelimited(e) { +abstract class IBM4690PackedIntegerDelimited(e: ElementBase) extends StringDelimited(e) { override lazy val parser: DaffodilParser = new IBM4690PackedIntegerDelimitedParser( e.elementRuntimeData, @@ -304,8 +301,8 @@ abstract class IBM4690PackedIntegerDelimited(e: ElementBase, signed: Boolean) ) } -case class IBM4690PackedIntegerDelimitedEndOfData(e: ElementBase, signed: Boolean) - extends IBM4690PackedIntegerDelimited(e, signed) { +case class IBM4690PackedIntegerDelimitedEndOfData(e: ElementBase) + extends IBM4690PackedIntegerDelimited(e) { val isDelimRequired: Boolean = false } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala index fef8199c69..c0f7a73ecd 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesPacked.scala @@ -36,12 +36,10 @@ import org.apache.daffodil.unparsers.runtime1.PackedIntegerRuntimeLengthUnparser class PackedIntegerRuntimeLength( val e: ElementBase, - signed: Boolean, packedSignCodes: PackedSignCodes ) extends Terminal(e, true) { override lazy val parser = new PackedIntegerRuntimeLengthParser( e.elementRuntimeData, - signed, packedSignCodes, e.lengthEv, e.lengthUnits @@ -57,14 +55,12 @@ class PackedIntegerRuntimeLength( class PackedIntegerKnownLength( val e: ElementBase, - signed: Boolean, packedSignCodes: PackedSignCodes, lengthInBits: Long ) extends Terminal(e, true) { override lazy val parser = new PackedIntegerKnownLengthParser( e.elementRuntimeData, - signed, packedSignCodes, lengthInBits.toInt ) @@ -78,7 +74,6 @@ class PackedIntegerKnownLength( class PackedIntegerPrefixedLength( val e: ElementBase, - signed: Boolean, packedSignCodes: PackedSignCodes ) extends Terminal(e, true) { @@ -86,7 +81,6 @@ class PackedIntegerPrefixedLength( e.elementRuntimeData, e.prefixedLengthBody.parser, e.prefixedLengthElementDecl.elementRuntimeData, - signed, packedSignCodes, e.lengthUnits, e.prefixedLengthAdjustmentInUnits diff --git a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd index d0e2f4a087..69ea3fdbb5 100644 --- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd +++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd @@ -137,6 +137,14 @@ + + + + When processing signed binary integers, which should have a length of at least 2 bits, issue + a warning if the length is less than 2 bits by default, otherwise (if false) issue a SDE or Processing Error. + + + @@ -734,6 +742,7 @@ + diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala index 2c5745fba0..b4f99d9ab2 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala @@ -24,13 +24,16 @@ import org.apache.daffodil.io.FormatInfo import org.apache.daffodil.lib.exceptions.Assert import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.lib.schema.annotation.props.gen.YesNo +import org.apache.daffodil.lib.schema.annotation.props.gen.YesNo.Yes import org.apache.daffodil.lib.util.Maybe._ import org.apache.daffodil.lib.util.MaybeInt import org.apache.daffodil.lib.util.Numbers._ +import org.apache.daffodil.runtime1.dpath.NodeInfo import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState import org.apache.daffodil.runtime1.processors.Processor +import org.apache.daffodil.runtime1.processors.parsers.BinaryNumberCheckWidth import org.apache.daffodil.runtime1.processors.parsers.HasKnownLengthInBits import org.apache.daffodil.runtime1.processors.parsers.HasRuntimeExplicitLength import org.apache.daffodil.runtime1.processors.unparsers._ @@ -56,12 +59,7 @@ abstract class BinaryNumberBaseUnparser(override val context: ElementRuntimeData val nBits = getBitLength(state) val value = getNumberToPut(state) val dos = state.dataOutputStream - val res = - if (nBits > 0) { - putNumber(dos, value, nBits, state) - } else { - true - } + val res = putNumber(dos, value, nBits, state) if (!res) { Assert.invariant(dos.maybeRelBitLimit0b.isDefined) @@ -78,8 +76,11 @@ abstract class BinaryNumberBaseUnparser(override val context: ElementRuntimeData } -abstract class BinaryIntegerBaseUnparser(e: ElementRuntimeData, signed: Boolean) - extends BinaryNumberBaseUnparser(e) { +abstract class BinaryIntegerBaseUnparser(e: ElementRuntimeData) + extends BinaryNumberBaseUnparser(e) + with BinaryNumberCheckWidth { + + private val primNumeric = e.optPrimType.get.asInstanceOf[NodeInfo.PrimType.PrimNumeric] override def putNumber( dos: DataOutputStream, @@ -87,8 +88,18 @@ abstract class BinaryIntegerBaseUnparser(e: ElementRuntimeData, signed: Boolean) nBits: Int, finfo: FormatInfo ): Boolean = { + val state = finfo.asInstanceOf[UState] + if (primNumeric.minWidth.isDefined) { + val minWidth = primNumeric.minWidth.get + val isSigned = primNumeric.isSigned + checkMinWidth(state, isSigned, nBits, minWidth) + } + if (primNumeric.maxWidth.isDefined) { + val maxWidth = primNumeric.maxWidth.get + checkMaxWidth(state, nBits, maxWidth) + } if (nBits > 64) { - dos.putBigInt(asBigInt(value), nBits, signed, finfo) + dos.putBigInt(asBigInt(value), nBits, primNumeric.isSigned, finfo) } else { dos.putLong(asLong(value), nBits, finfo) } @@ -97,9 +108,8 @@ abstract class BinaryIntegerBaseUnparser(e: ElementRuntimeData, signed: Boolean) class BinaryIntegerKnownLengthUnparser( e: ElementRuntimeData, - signed: Boolean, override val lengthInBits: Int -) extends BinaryIntegerBaseUnparser(e, signed) +) extends BinaryIntegerBaseUnparser(e) with HasKnownLengthInBits { override lazy val runtimeDependencies = Vector() @@ -108,10 +118,9 @@ class BinaryIntegerKnownLengthUnparser( class BinaryIntegerRuntimeLengthUnparser( val e: ElementRuntimeData, - signed: Boolean, val lengthEv: Evaluatable[JLong], val lengthUnits: LengthUnits -) extends BinaryIntegerBaseUnparser(e, signed) +) extends BinaryIntegerBaseUnparser(e) with HasRuntimeExplicitLength { override val runtimeDependencies = Vector(lengthEv) @@ -122,12 +131,13 @@ class BinaryIntegerPrefixedLengthUnparser( override val prefixedLengthUnparser: Unparser, override val prefixedLengthERD: ElementRuntimeData, maybeNBits: MaybeInt, - signed: Boolean, override val lengthUnits: LengthUnits, override val prefixedLengthAdjustmentInUnits: Long -) extends BinaryIntegerBaseUnparser(e: ElementRuntimeData, signed: Boolean) +) extends BinaryIntegerBaseUnparser(e: ElementRuntimeData) with KnownPrefixedLengthUnparserMixin { + private val primNumeric = e.optPrimType.get.asInstanceOf[NodeInfo.PrimType.PrimNumeric] + override def childProcessors: Vector[Processor] = Vector(prefixedLengthUnparser) override lazy val runtimeDependencies = Vector() @@ -140,7 +150,7 @@ class BinaryIntegerPrefixedLengthUnparser( // bytes needed to represent the number val value = getNumberToPut(s.asInstanceOf[UState]) val len = Math.max(asBigInt(value).bitLength, 1) - val signedLen = if (signed) len + 1 else len + val signedLen = if (primNumeric.isSigned) len + 1 else len (signedLen + 7) & ~0x7 // round up to nearest multilpe of 8 } } @@ -241,7 +251,8 @@ abstract class BinaryDecimalUnparserBase( e: ElementRuntimeData, signed: YesNo, binaryDecimalVirtualPoint: Int -) extends BinaryNumberBaseUnparser(e) { +) extends BinaryNumberBaseUnparser(e) + with BinaryNumberCheckWidth { override def getNumberToPut(state: UState): JNumber = { val node = state.currentInfosetNode.asSimple @@ -268,6 +279,10 @@ abstract class BinaryDecimalUnparserBase( nBits: Int, finfo: FormatInfo ): Boolean = { - dos.putBigInt(asBigInt(value), nBits, signed == YesNo.Yes, finfo) + val state = finfo.asInstanceOf[UState] + val isSigned: Boolean = signed == Yes + val minWidth: Int = if (isSigned) 2 else 1 + checkMinWidth(state, isSigned, nBits, minWidth) + dos.putBigInt(asBigInt(value), nBits, isSigned, finfo) } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DFDLXFunctions.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DFDLXFunctions.scala index 5cec60fff4..106d4740e2 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DFDLXFunctions.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/DFDLXFunctions.scala @@ -54,7 +54,7 @@ case class DFDLXLeftShift(recipes: List[CompiledDPath], argType: NodeInfo.Kind) val shiftLong = arg2.getLong val shift = shiftLong.toInt - val width = argType.asInstanceOf[PrimNumeric].width.get + val width = argType.asInstanceOf[PrimNumeric].maxWidth.get Assert.invariant(shift >= 0) if (shift >= width) dstate.SDE( @@ -101,7 +101,7 @@ case class DFDLXRightShift(recipes: List[CompiledDPath], argType: NodeInfo.Kind) ): DataValuePrimitive = { val shiftLong = arg2.getLong val shift = shiftLong.toInt - val width = argType.asInstanceOf[PrimNumeric].width.get + val width = argType.asInstanceOf[PrimNumeric].maxWidth.get Assert.invariant(shift >= 0) if (shift >= width) dstate.SDE( diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala index cb94dec31f..5ce59bf1ac 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala @@ -534,7 +534,9 @@ object NodeInfo extends Enum { } trait PrimNumeric { self: Numeric.Kind => - def width: MaybeInt + def isSigned: Boolean + def minWidth: MaybeInt + def maxWidth: MaybeInt def isValid(n: Number): Boolean protected def fromNumberNoCheck(n: Number): DataValueNumber def fromNumber(n: Number): DataValueNumber = { @@ -648,7 +650,9 @@ object NodeInfo extends Enum { // toString would have a precision different than Float.MaxValue.toString override val minStr = "-" + JFloat.MAX_VALUE.toString override val maxStr = JFloat.MAX_VALUE.toString - override val width: MaybeInt = MaybeInt(32) + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt(32) + override val maxWidth: MaybeInt = MaybeInt(32) } protected sealed trait DoubleKind extends SignedNumeric.Kind @@ -667,7 +671,9 @@ object NodeInfo extends Enum { override val max = JDouble.MAX_VALUE override val minStr = "-" + JDouble.MAX_VALUE.toString override val maxStr = JDouble.MAX_VALUE.toString - override val width: MaybeInt = MaybeInt(64) + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt(64) + override val maxWidth: MaybeInt = MaybeInt(64) } protected sealed trait DecimalKind extends SignedNumeric.Kind @@ -686,8 +692,9 @@ object NodeInfo extends Enum { case _ => true } } - - override val width: MaybeInt = MaybeInt.Nope + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt.Nope + override val maxWidth: MaybeInt = MaybeInt.Nope override def isInteger = false } @@ -708,8 +715,9 @@ object NodeInfo extends Enum { case _ => true } } - - override val width: MaybeInt = MaybeInt.Nope + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt(2) + override val maxWidth: MaybeInt = MaybeInt.Nope override def isInteger = true } @@ -725,7 +733,9 @@ object NodeInfo extends Enum { protected override def fromNumberNoCheck(n: Number): DataValueLong = n.longValue override val min = JLong.MIN_VALUE override val max = JLong.MAX_VALUE - override val width: MaybeInt = MaybeInt(64) + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt(2) + override val maxWidth: MaybeInt = MaybeInt(64) } protected sealed trait IntKind extends Long.Kind @@ -739,7 +749,9 @@ object NodeInfo extends Enum { protected override def fromNumberNoCheck(n: Number): DataValueInt = n.intValue override val min = JInt.MIN_VALUE.toLong override val max = JInt.MAX_VALUE.toLong - override val width: MaybeInt = MaybeInt(32) + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt(2) + override val maxWidth: MaybeInt = MaybeInt(32) } protected sealed trait ShortKind extends Int.Kind @@ -753,7 +765,9 @@ object NodeInfo extends Enum { protected override def fromNumberNoCheck(n: Number): DataValueShort = n.shortValue override val min = JShort.MIN_VALUE.toLong override val max = JShort.MAX_VALUE.toLong - override val width: MaybeInt = MaybeInt(16) + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt(2) + override val maxWidth: MaybeInt = MaybeInt(16) } protected sealed trait ByteKind extends Short.Kind @@ -767,7 +781,9 @@ object NodeInfo extends Enum { protected override def fromNumberNoCheck(n: Number): DataValueByte = n.byteValue override val min = JByte.MIN_VALUE.toLong override val max = JByte.MAX_VALUE.toLong - override val width: MaybeInt = MaybeInt(8) + override val isSigned: Boolean = true + override val minWidth: MaybeInt = MaybeInt(2) + override val maxWidth: MaybeInt = MaybeInt(8) } protected sealed trait NonNegativeIntegerKind extends Integer.Kind @@ -786,8 +802,9 @@ object NodeInfo extends Enum { case f: JFloat if f.isInfinite || f.isNaN => false case _ => n.longValue >= 0 } - - override val width: MaybeInt = MaybeInt.Nope + override val isSigned: Boolean = false + override val minWidth: MaybeInt = MaybeInt(1) + override val maxWidth: MaybeInt = MaybeInt.Nope override def isInteger = true } @@ -814,7 +831,9 @@ object NodeInfo extends Enum { } val max = new JBigInt(1, scala.Array.fill(8)(0xff.toByte)) val maxBD = new JBigDecimal(max) - override val width: MaybeInt = MaybeInt(64) + override val isSigned: Boolean = false + override val minWidth: MaybeInt = MaybeInt(1) + override val maxWidth: MaybeInt = MaybeInt(64) override def isInteger = true } @@ -834,7 +853,9 @@ object NodeInfo extends Enum { protected override def fromNumberNoCheck(n: Number): DataValueLong = n.longValue override val min = 0L override val max = 0xffffffffL - override val width: MaybeInt = MaybeInt(32) + override val isSigned: Boolean = false + override val minWidth: MaybeInt = MaybeInt(1) + override val maxWidth: MaybeInt = MaybeInt(32) } protected sealed trait UnsignedShortKind extends UnsignedInt.Kind @@ -848,7 +869,9 @@ object NodeInfo extends Enum { protected override def fromNumberNoCheck(n: Number): DataValueInt = n.intValue override val min = 0L override val max = 0xffffL - override val width: MaybeInt = MaybeInt(16) + override val isSigned: Boolean = false + override val minWidth: MaybeInt = MaybeInt(1) + override val maxWidth: MaybeInt = MaybeInt(16) } protected sealed trait UnsignedByteKind extends UnsignedShort.Kind @@ -862,7 +885,9 @@ object NodeInfo extends Enum { protected override def fromNumberNoCheck(n: Number): DataValueShort = n.shortValue override val min = 0L override val max = 0xffL - override val width: MaybeInt = MaybeInt(8) + override val isSigned: Boolean = false + override val minWidth: MaybeInt = MaybeInt(1) + override val maxWidth: MaybeInt = MaybeInt(8) } protected sealed trait StringKind extends AnyAtomic.Kind diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala index 36067c404f..dc2799262f 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/IBM4690PackedDecimalParsers.scala @@ -81,10 +81,9 @@ class IBM4690PackedDecimalPrefixedLengthParser( class IBM4690PackedIntegerRuntimeLengthParser( val e: ElementRuntimeData, - signed: Boolean, val lengthEv: Evaluatable[JLong], val lengthUnits: LengthUnits -) extends PackedBinaryIntegerBaseParser(e, signed) +) extends PackedBinaryIntegerBaseParser(e) with HasRuntimeExplicitLength { override def toBigInteger(num: Array[Byte]): JBigInteger = @@ -96,9 +95,8 @@ class IBM4690PackedIntegerRuntimeLengthParser( class IBM4690PackedIntegerKnownLengthParser( e: ElementRuntimeData, - signed: Boolean, val lengthInBits: Int -) extends PackedBinaryIntegerBaseParser(e, signed) +) extends PackedBinaryIntegerBaseParser(e) with HasKnownLengthInBits { override def toBigInteger(num: Array[Byte]): JBigInteger = @@ -112,10 +110,9 @@ class IBM4690PackedIntegerPrefixedLengthParser( e: ElementRuntimeData, override val prefixedLengthParser: Parser, override val prefixedLengthERD: ElementRuntimeData, - signed: Boolean, override val lengthUnits: LengthUnits, override val prefixedLengthAdjustmentInUnits: Long -) extends PackedBinaryIntegerBaseParser(e, signed) +) extends PackedBinaryIntegerBaseParser(e) with PrefixedLengthParserMixin { override def toBigInteger(num: Array[Byte]): JBigInteger = diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedBinaryTraits.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedBinaryTraits.scala index 5030e0a687..e992768059 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedBinaryTraits.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedBinaryTraits.scala @@ -26,6 +26,7 @@ import org.apache.daffodil.lib.equality.TypeEqual import org.apache.daffodil.lib.exceptions.Assert import org.apache.daffodil.lib.util.Maybe import org.apache.daffodil.lib.util.MaybeChar +import org.apache.daffodil.runtime1.dpath.NodeInfo import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.FieldDFAParseEv import org.apache.daffodil.runtime1.processors.ParseOrUnparseState @@ -51,7 +52,14 @@ abstract class PackedBinaryDecimalBaseParser( def parse(start: PState): Unit = { val nBits = getBitLength(start) - if (nBits == 0) return // zero length is used for outputValueCalc often. + if (nBits == 0) { + PE( + start, + "Number of bits %d out of range for a packed decimal.", + nBits + ) + return + } val dis = start.dataInputStream if (!dis.isDefinedForLength(nBits)) { @@ -69,17 +77,30 @@ abstract class PackedBinaryDecimalBaseParser( } abstract class PackedBinaryIntegerBaseParser( - override val context: ElementRuntimeData, - signed: Boolean = false + override val context: ElementRuntimeData ) extends PrimParser with PackedBinaryConversion { override lazy val runtimeDependencies = Vector() + val signed = { + context.optPrimType.get match { + case n: NodeInfo.PrimType.PrimNumeric => n.isSigned + // context.optPrimType can be of type date/time via ConvertZonedCombinator + case _ => false + } + } protected def getBitLength(s: ParseOrUnparseState): Int def parse(start: PState): Unit = { val nBits = getBitLength(start) - if (nBits == 0) return // zero length is used for outputValueCalc often. + if (nBits == 0) { + PE( + start, + "Number of bits %d out of range for a packed integer.", + nBits + ) + return + } val dis = start.dataInputStream if (!dis.isDefinedForLength(nBits)) { diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala index 248322f3e1..6f130de9f6 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/PackedDecimalParsers.scala @@ -84,11 +84,10 @@ class PackedDecimalPrefixedLengthParser( class PackedIntegerRuntimeLengthParser( val e: ElementRuntimeData, - signed: Boolean, packedSignCodes: PackedSignCodes, val lengthEv: Evaluatable[JLong], val lengthUnits: LengthUnits -) extends PackedBinaryIntegerBaseParser(e, signed) +) extends PackedBinaryIntegerBaseParser(e) with HasRuntimeExplicitLength { override def toBigInteger(num: Array[Byte]): JBigInteger = @@ -100,10 +99,9 @@ class PackedIntegerRuntimeLengthParser( class PackedIntegerKnownLengthParser( e: ElementRuntimeData, - signed: Boolean, packedSignCodes: PackedSignCodes, val lengthInBits: Int -) extends PackedBinaryIntegerBaseParser(e, signed) +) extends PackedBinaryIntegerBaseParser(e) with HasKnownLengthInBits { override def toBigInteger(num: Array[Byte]): JBigInteger = @@ -117,11 +115,10 @@ class PackedIntegerPrefixedLengthParser( e: ElementRuntimeData, override val prefixedLengthParser: Parser, override val prefixedLengthERD: ElementRuntimeData, - signed: Boolean, packedSignCodes: PackedSignCodes, override val lengthUnits: LengthUnits, override val prefixedLengthAdjustmentInUnits: Long -) extends PackedBinaryIntegerBaseParser(e, signed) +) extends PackedBinaryIntegerBaseParser(e) with PrefixedLengthParserMixin { override def toBigInteger(num: Array[Byte]): JBigInteger = diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala index a373be2fbc..fac7a9078f 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/BinaryNumberParsers.scala @@ -22,12 +22,14 @@ import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInt } import org.apache.daffodil.lib.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.lib.schema.annotation.props.gen.YesNo +import org.apache.daffodil.lib.schema.annotation.props.gen.YesNo.Yes import org.apache.daffodil.runtime1.dpath.InvalidPrimitiveDataException import org.apache.daffodil.runtime1.dpath.NodeInfo import org.apache.daffodil.runtime1.processors.ElementRuntimeData import org.apache.daffodil.runtime1.processors.Evaluatable import org.apache.daffodil.runtime1.processors.ParseOrUnparseState import org.apache.daffodil.runtime1.processors.Processor +import org.apache.daffodil.runtime1.processors.unparsers.UState class BinaryFloatParser(override val context: ElementRuntimeData) extends PrimParser { override lazy val runtimeDependencies = Vector() @@ -100,13 +102,18 @@ abstract class BinaryDecimalParserBase( override val context: ElementRuntimeData, signed: YesNo, binaryDecimalVirtualPoint: Int -) extends PrimParser { +) extends PrimParser + with BinaryNumberCheckWidth { override lazy val runtimeDependencies = Vector() protected def getBitLength(s: ParseOrUnparseState): Int def parse(start: PState): Unit = { val nBits = getBitLength(start) + val isSigned = signed == Yes + val minWidth = if (isSigned) 2 else 1 + val res = checkMinWidth(start, isSigned, nBits, minWidth) + if (!res) return val dis = start.dataInputStream if (!dis.isDefinedForLength(nBits)) { PENotEnoughBits(start, nBits, dis) @@ -124,27 +131,24 @@ abstract class BinaryDecimalParserBase( class BinaryIntegerRuntimeLengthParser( val e: ElementRuntimeData, - signed: Boolean, val lengthEv: Evaluatable[JLong], val lengthUnits: LengthUnits -) extends BinaryIntegerBaseParser(e, signed) +) extends BinaryIntegerBaseParser(e) with HasRuntimeExplicitLength {} class BinaryIntegerKnownLengthParser( e: ElementRuntimeData, - signed: Boolean, val lengthInBits: Int -) extends BinaryIntegerBaseParser(e, signed) +) extends BinaryIntegerBaseParser(e) with HasKnownLengthInBits {} class BinaryIntegerPrefixedLengthParser( e: ElementRuntimeData, override val prefixedLengthParser: Parser, override val prefixedLengthERD: ElementRuntimeData, - signed: Boolean, override val lengthUnits: LengthUnits, override val prefixedLengthAdjustmentInUnits: Long -) extends BinaryIntegerBaseParser(e, signed) +) extends BinaryIntegerBaseParser(e) with PrefixedLengthParserMixin { override def childProcessors: Vector[Processor] = Vector(prefixedLengthParser) @@ -155,9 +159,9 @@ class BinaryIntegerPrefixedLengthParser( } abstract class BinaryIntegerBaseParser( - override val context: ElementRuntimeData, - signed: Boolean -) extends PrimParser { + override val context: ElementRuntimeData +) extends PrimParser + with BinaryNumberCheckWidth { override lazy val runtimeDependencies = Vector() protected def getBitLength(s: ParseOrUnparseState): Int @@ -166,16 +170,16 @@ abstract class BinaryIntegerBaseParser( def parse(start: PState): Unit = { val nBits = getBitLength(start) - if (nBits == 0) return // zero length is used for outputValueCalc often. - if (primNumeric.width.isDefined) { - val width = primNumeric.width.get - if (nBits > width) - PE( - start, - "Number of bits %d out of range, must be between 1 and %d bits.", - nBits, - width - ) + if (primNumeric.minWidth.isDefined) { + val minWidth = primNumeric.minWidth.get + val isSigned: Boolean = primNumeric.isSigned + val res = checkMinWidth(start, isSigned, nBits, minWidth) + if (!res) return + } + if (primNumeric.maxWidth.isDefined) { + val maxWidth = primNumeric.maxWidth.get + val res = checkMaxWidth(start, nBits, maxWidth) + if (!res) return } val dis = start.dataInputStream if (!dis.isDefinedForLength(nBits)) { @@ -184,7 +188,7 @@ abstract class BinaryIntegerBaseParser( } val num: JNumber = - if (signed) { + if (primNumeric.isSigned) { if (nBits > 64) { dis.getSignedBigInt(nBits, start) } else { dis.getSignedLong(nBits, start) } } else { @@ -205,3 +209,46 @@ abstract class BinaryIntegerBaseParser( start.simpleElement.overwriteDataValue(res) } } + +trait BinaryNumberCheckWidth { + def checkMinWidth( + state: ParseOrUnparseState, + isSigned: Boolean, + nBits: Int, + minWidth: Int + ): Boolean = { + if ( + nBits < minWidth && !(isSigned && state.tunable.allowSignedIntegerLength1Bit && nBits == 1) + ) { + val signedStr = if (isSigned) "a signed" else "an unsigned" + val outOfRangeStr = + s"Minimum length for $signedStr binary number is $minWidth bit(s), number of bits $nBits out of range. " + + "An unsigned number with length 1 bit could be used instead." + val procErr = state.toProcessingError(outOfRangeStr) + state match { + case s: PState => + s.setFailed(procErr) + return false + case s: UState => + s.toss(procErr) + } + } + true + } + + def checkMaxWidth(state: ParseOrUnparseState, nBits: Int, maxWidth: Int): Boolean = { + if (nBits > maxWidth) { + val procErr = state.toProcessingError( + s"Number of bits $nBits out of range, must be between 1 and $maxWidth bits." + ) + state match { + case s: PState => + s.setFailed(procErr) + return false + case s: UState => + s.toss(procErr) + } + } + true + } +} diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/extensions/enum/enums.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/extensions/enum/enums.tdml index 7923ae7c44..4205964498 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/extensions/enum/enums.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/extensions/enum/enums.tdml @@ -134,7 +134,7 @@ - + diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml index 88bb887021..1467b4e701 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml @@ -2521,7 +2521,7 @@ - + @@ -2537,7 +2537,10 @@ - a + + 1 + a + Runtime Schema Definition Error dfdl:bitOrder diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section11/content_framing_properties/ContentFramingProps.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section11/content_framing_properties/ContentFramingProps.tdml index 20f7cb22ec..fe747f4a97 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/section11/content_framing_properties/ContentFramingProps.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section11/content_framing_properties/ContentFramingProps.tdml @@ -1319,7 +1319,7 @@ - + + + + + 64 + 32 + + + + + 64 out of range + between 1 and 32 + + + @@ -1490,7 +1506,7 @@ - + @@ -1521,4 +1537,635 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + ff + + + + Schema Definition Error + unsigned binary integer + 1 bit(s) + 0 out of range + + + + + + + ff + + + + Schema Definition Error + signed binary integer + 2 bit(s) + 1 out of range + + + + + + + 0 + + + + Schema Definition Error + unsigned binary integer + 1 bit(s) + 0 out of range + + + + + + + 0 + + + + Schema Definition Error + signed binary integer + 2 bit(s) + 1 out of range + + + + + + + + + -1 + + + + + Unparse Error + signed binary number + 2 bit(s) + 1 out of range + + + + + + + + 0 + 65535 + + + + + Unparse Error + unsigned binary number + 1 bit(s) + 0 out of range + + + + + + + 1 + -1 + + + + + 0180 + + + + + + 01 + 1 + + + + + 1 + 1 + + + + + + + + 1 + + + + 1 + + + + Schema Definition Warning + signed binary integer + 2 bit(s) + 1 out of range + + + + + + 00123C + + + Parse Error + 0 out of range + + + + + + 001088 + + + Parse Error + 0 out of range + + + + + + 00123C + + + Parse Error + 0 out of range + + + + + + 001088 + + + Parse Error + 0 out of range + + + + + + + 1 + + + + + 1 + + + + + + + + 11 + + + + + -1 + + + + + + + + 11 + + + + + -1 + + + + + + + + 1 + + + + + 1 + + + + + + + + + 2 + -1 + + + + + 02 + 11 + + + + + + 02123C + + + + + 2 + 123 + + + + + + + + 021088 + + + + + 2 + 1088 + + + + + + + + 02 + 11 + + + + + 2 + -1 + + + + + + + + + + 1 + 1 + + + + + 01 + 1 + + + + + + + 4668 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ff + + + + Parse Error + unsigned binary number + 1 bit(s) + 0 out of range + + + + + + + ff + + + + Parse Error + signed binary number + 2 bit(s) + 1 out of range + + + + + + + 1 + + + + Unparse Error + unsigned binary number + 1 bit(s) + 0 out of range + + + + + + + 1 + + + + Unparse Error + signed binary number + 2 bit(s) + 1 out of range + + + + + + 1 + + + + 1 + + + + + + + + 1 + + + + 1 + + + + + + 00 + 1 + + + Parse Error + signed binary number + 2 bit(s) + 0 out of range + + + + + + + + 0 + 1 + + + + + Unparse Error + signed binary number + 2 bit(s) + 0 out of range + + + + + + 00 + 1 + + + Parse Error + signed binary number + 1 bit(s) + 0 out of range + + + + + + + + 0 + 1 + + + + + Unparse Error + signed binary number + 1 bit(s) + 0 out of range + + diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/length_properties/LengthProperties.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/length_properties/LengthProperties.tdml index 866691abc0..52c8ed0f08 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/length_properties/LengthProperties.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/length_properties/LengthProperties.tdml @@ -913,7 +913,7 @@ - + @@ -922,15 +922,15 @@ - + - - + + - + @@ -1118,7 +1118,7 @@ - + @@ -1190,7 +1190,7 @@ - + @@ -1245,10 +1245,10 @@ root="s4" model="bitSchema" description="Section 12 Length Properties - DFDL-12-161R"> 00101010 - 1 + 01 00000000 00000000 00000000 00000001 - 0 - 1 + 00 + 01 diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindExplicit.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindExplicit.scala index f8a62cb6de..c787fc2267 100644 --- a/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindExplicit.scala +++ b/daffodil-test/src/test/scala/org/apache/daffodil/section12/lengthKind/TestLengthKindExplicit.scala @@ -164,6 +164,9 @@ class TestLengthKindExplicit { @Test def test_invalidIntBitLengthExpr(): Unit = { runner.runOneTest("invalidIntBitLengthExpr") } + @Test def test_unparseInvalidIntBitLengthExpr(): Unit = { + runner.runOneTest("unparseInvalidIntBitLengthExpr") + } @Test def test_invalidShortBitLengthExpr(): Unit = { runner.runOneTest("invalidShortBitLengthExpr") @@ -180,4 +183,105 @@ class TestLengthKindExplicit { @Test def test_insufficientBitsByte(): Unit = { runner.runOneTest("insufficientBitsByte") } + + // DFDL-2297 + @Test def test_outOfRangeLengthBinaryInteger1(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger1") + } + @Test def test_outOfRangeLengthBinaryInteger2(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger2") + } + @Test def test_outOfRangeLengthBinaryInteger3(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger3") + } + @Test def test_outOfRangeLengthBinaryInteger4(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger4") + } + @Test def test_outOfRangeLengthBinaryInteger5(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger5") + } + @Test def test_outOfRangeLengthBinaryInteger6(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger6") + } + @Test def test_outOfRangeLengthBinaryInteger7(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger7") + } + @Test def test_outOfRangeLengthBinaryInteger8(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger8") + } + @Test def test_outOfRangeLengthBinaryInteger9(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger9") + } + @Test def test_outOfRangeLengthBinaryInteger10(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger10") + } + @Test def test_outOfRangeLengthBinaryInteger11(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger11") + } + @Test def test_outOfRangeLengthBinaryInteger12(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger12") + } + @Test def test_outOfRangeLengthBinaryInteger13(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryInteger13") + } + @Test def test_inRangeLengthBinaryInteger1(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger1") + } + @Test def test_inRangeLengthBinaryInteger2(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger2") + } + @Test def test_inRangeLengthBinaryInteger3(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger3") + } + @Test def test_inRangeLengthBinaryInteger4(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger4") + } + @Test def test_inRangeLengthBinaryInteger5(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger5") + } + @Test def test_inRangeLengthBinaryInteger6(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger6") + } + @Test def test_inRangeLengthBinaryInteger7(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger7") + } + @Test def test_inRangeLengthBinaryInteger8(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger8") + } + @Test def test_inRangeLengthBinaryInteger9(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger9") + } + @Test def test_inRangeLengthBinaryInteger10(): Unit = { + runner.runOneTest("inRangeLengthBinaryInteger10") + } + @Test def test_outOfRangeLengthBinaryDecimal1(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal1") + } + @Test def test_outOfRangeLengthBinaryDecimal2(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal2") + } + @Test def test_outOfRangeLengthBinaryDecimal3(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal3") + } + @Test def test_outOfRangeLengthBinaryDecimal4(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal4") + } + @Test def test_outOfRangeLengthBinaryDecimal5(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal5") + } + @Test def test_outOfRangeLengthBinaryDecimal6(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal6") + } + @Test def test_outOfRangeLengthBinaryDecimal7(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal7") + } + @Test def test_outOfRangeLengthBinaryDecimal8(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal8") + } + @Test def test_outOfRangeLengthBinaryDecimal9(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal9") + } + @Test def test_outOfRangeLengthBinaryDecimal10(): Unit = { + runner.runOneTest("outOfRangeLengthBinaryDecimal10") + } }