Skip to content

Fix Int overflow in binary number lengths - #1760

Open
stevedlawrence wants to merge 1 commit into
apache:mainfrom
stevedlawrence:daffodil-3088-binary-number-int-overflow
Open

stevedlawrence wants to merge 1 commit into
apache:mainfrom
stevedlawrence:daffodil-3088-binary-number-int-overflow

Conversation

@stevedlawrence

Copy link
Copy Markdown
Member

getBitLength currently returns an Int, with implementations often using Long.toInt. This can lead to silent overflow/truncation (e.g. with dfdl:length runtime expressions). To resolve this, getBitLength is modified to return a Long so that no truncation needs to happen.

Ultimately these lengths need to be converted to integers for the various IO functions, so additional functions are added to ensure we also check the lengths prior to casting to an int. For types that have unlimited lengths (e.g. xs:integer, xs:decimal, packed decimals) a new tunable is added to restrict binary number lengths to reasonable values. This tunable has an xs:int base so if the checks pass the cast from long to int should never overflow.

Also replaces the various packed DelimiterUnparsers with the packed MinimumLengthUnparsers. The DelimiterUnparsers have getBitLength return 0 which fails the checks. The MimumLengthUnparers calculate the actual length of the packed fields, which can then be checked against the tunable.

DAFFODIL-3088

getBitLength currently returns an Int, with implementations often using
Long.toInt. This can lead to silent overflow/truncation (e.g. with
dfdl:length runtime expressions). To resolve this, getBitLength is
modified to return a Long so that no truncation needs to happen.

Ultimately these lengths need to be converted to integers for the
various IO functions, so additional functions are added to ensure we
also check the lengths prior to casting to an int. For types that have
unlimited lengths (e.g. xs:integer, xs:decimal, packed decimals) a new
tunable is added to restrict binary number lengths to reasonable values.
This tunable has an xs:int base so if the checks pass the cast from long
to int should never overflow.

Also replaces the various packed DelimiterUnparsers with the
packed MinimumLengthUnparsers. The DelimiterUnparsers have getBitLength
return 0 which fails the checks. The MimumLengthUnparers calculate the
actual length of the packed fields, which can then be checked against
the tunable.

DAFFODIL-3088
@stevedlawrence
stevedlawrence force-pushed the daffodil-3088-binary-number-int-overflow branch from 314072d to 40096aa Compare October 19, 2026 16:35

@jadams-tresys jadams-tresys left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Just a couple places where we are converting back to .toInt that I want to make sure aren't a problem


try {
val int = toPrimType(context, dis.getByteArray(nBits, start))
val int = toPrimType(context, dis.getByteArray(nBits.toInt, start))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know if it matters or not, but there is still potential for an overflow/truncation here. For dis.getUnsignedLong it looks like there is a check to ensure that nBits is between 1 and 64, but there is no check for getByteArray


if (nBits > 64) {
dos.putBigInt(asBigInt(value), nBits, primNumeric.isSigned, finfo)
dos.putBigInt(asBigInt(value), nBits.toInt, primNumeric.isSigned, finfo)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this overflow as well or does checkMaxWidth ensure that nBits would be able to be stored in an int?

if (binaryBooleanTrueRep.isDefined) binaryBooleanTrueRep.getULong
else ~binaryBooleanFalseRep
putNumber(dos, trueRep, nBits, state)
putNumber(dos, trueRep, nBits.toInt, state)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these putNumber calls need to worry about integer overflow/truncation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants