[jira] [Updated] (XERCESC-2263) NaN bypasses minInclusive/maxInclusive bounds check via unhandled compareValues INDETERMINATE(2) result
"Guichard Desrosiers (Jira)" <[email protected]> Tue, 14 Apr 2026 03:59:00 +0000 (UTC)
| Newsgroups | gmane.text.xml.xerces-c.devel |
|---|---|
| Message-ID | <[email protected]> |
[ https://issues.apache.org/jira/browse/XERCESC-2263?page=3Dcom.atlass=
ian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Guichard Desrosiers updated XERCESC-2263:
-----------------------------------------
Description:=20
SUMMARY
-------
NaN silently passes minInclusive and maxInclusive facet validation on xs:do=
uble and xs:float types.=C2=A0
This is a regression caused by a mismatch between compareValues return doma=
in and boundsCheck=C2=A0
handling logic.
ROOT CAUSE
----------
compareValues was updated at some point to return 2 (INDETERMINATE) for NaN=
comparisons instead=C2=A0
of 1. The boundsCheck logic in minInclusive and maxInclusive was never upda=
ted to account for=C2=A0
this 4th return value, breaking the assumed trichotomy of \{-1, 0, 1}.
compareValues return values:
=C2=A0 -1 =C2=A0=E2=86=92 less than
=C2=A0 =C2=A00 =C2=A0=E2=86=92 equal
=C2=A0 =C2=A01 =C2=A0=E2=86=92 greater than
=C2=A0 =C2=A02 =C2=A0=E2=86=92 INDETERMINATE (NaN)
Buggy checks:
=C2=A0 minInclusive: if (result =3D=3D -1) =E2=86=92 FAIL =C2=A0 misses IND=
ETERMINATE(2) =E2=86=92 NaN passes =E2=9C=97
=C2=A0 maxInclusive: if (result =3D=3D 1) =C2=A0=E2=86=92 FAIL =C2=A0 misse=
s INDETERMINATE(2) =E2=86=92 NaN passes =E2=9C=97
UNAFFECTED FACETS
-----------------
minExclusive and maxExclusive are not affected as their inverted logic inci=
dentally catches=C2=A0
INDETERMINATE(2):
=C2=A0 minExclusive: if (result !=3D 1) =C2=A0=E2=86=92 FAIL =C2=A0 catches=
-1, 0, and 2 =E2=9C=93
=C2=A0 maxExclusive: if (result !=3D -1) =E2=86=92 FAIL =C2=A0 catches =C2=
=A00, 1, and 2 =E2=9C=93
AFFECTED FACETS
---------------
=C2=A0 xs:minInclusive on xs:double and xs:float
=C2=A0 xs:maxInclusive on xs:double and xs:float
FIX
=E2=80=94
Tighten acceptance condition to only pass on known-valid orderings:
=C2=A0 minInclusive: reject if (result !=3D 1 && result !=3D 0)
=C2=A0 maxInclusive: reject if (result !=3D -1 && result !=3D 0)
=C2=A0
{*}{*}PR: [fix: NaN bypasses minInclusive/maxInclusive facets by gdesrosier=
s1805 =C2=B7 Pull Request #64 =C2=B7 apache/xerces-c|https://github.com/apa=
che/xerces-c/pull/64]
=C2=A0
was:
SUMMARY
-------
NaN silently passes minInclusive and maxInclusive facet validation on xs:do=
uble and xs:float types.=C2=A0
This is a regression caused by a mismatch between compareValues return doma=
in and boundsCheck=C2=A0
handling logic.
ROOT CAUSE
----------
compareValues was updated at some point to return 2 (INDETERMINATE) for NaN=
comparisons instead=C2=A0
of 1. The boundsCheck logic in minInclusive and maxInclusive was never upda=
ted to account for=C2=A0
this 4th return value, breaking the assumed trichotomy of \{-1, 0, 1}.
compareValues return values:
=C2=A0 -1 =C2=A0=E2=86=92 less than
=C2=A0 =C2=A00 =C2=A0=E2=86=92 equal
=C2=A0 =C2=A01 =C2=A0=E2=86=92 greater than
=C2=A0 =C2=A02 =C2=A0=E2=86=92 INDETERMINATE (NaN)
Buggy checks:
=C2=A0 minInclusive: if (result =3D=3D -1) =E2=86=92 FAIL =C2=A0 misses IND=
ETERMINATE(2) =E2=86=92 NaN passes =E2=9C=97
=C2=A0 maxInclusive: if (result =3D=3D 1) =C2=A0=E2=86=92 FAIL =C2=A0 misse=
s INDETERMINATE(2) =E2=86=92 NaN passes =E2=9C=97
UNAFFECTED FACETS
-----------------
minExclusive and maxExclusive are not affected as their inverted logic inci=
dentally catches=C2=A0
INDETERMINATE(2):
=C2=A0 minExclusive: if (result !=3D 1) =C2=A0=E2=86=92 FAIL =C2=A0 catches=
-1, 0, and 2 =E2=9C=93
=C2=A0 maxExclusive: if (result !=3D -1) =E2=86=92 FAIL =C2=A0 catches =C2=
=A00, 1, and 2 =E2=9C=93
AFFECTED FACETS
---------------
=C2=A0 xs:minInclusive on xs:double and xs:float
=C2=A0 xs:maxInclusive on xs:double and xs:float
FIX
=E2=80=94
Tighten acceptance condition to only pass on known-valid orderings:
=C2=A0 minInclusive: reject if (result !=3D 1 && result !=3D 0)
=C2=A0 maxInclusive: reject if (result !=3D -1 && result !=3D 0)
=C2=A0
*{*}PR:{*}* [fix: NaN bypasses minInclusive/maxInclusive facets by gdesrosi=
ers1805 =C2=B7 Pull Request #64 =C2=B7 apache/xerces-c|https://github.com/a=
pache/xerces-c/pull/64]
=C2=A0
> NaN bypasses minInclusive/maxInclusive bounds check via unhandled compare=
Values INDETERMINATE(2) result
> -------------------------------------------------------------------------=
------------------------------
>
> Key: XERCESC-2263
> URL: https://issues.apache.org/jira/browse/XERCESC-2263
> Project: Xerces-C++
> Issue Type: Bug
> Components: Validating Parser (XML Schema)
> Reporter: Guichard Desrosiers
> Priority: Major
>
> SUMMARY
> -------
> NaN silently passes minInclusive and maxInclusive facet validation on xs:=
double and xs:float types.=C2=A0
> This is a regression caused by a mismatch between compareValues return do=
main and boundsCheck=C2=A0
> handling logic.
> ROOT CAUSE
> ----------
> compareValues was updated at some point to return 2 (INDETERMINATE) for N=
aN comparisons instead=C2=A0
> of 1. The boundsCheck logic in minInclusive and maxInclusive was never up=
dated to account for=C2=A0
> this 4th return value, breaking the assumed trichotomy of \{-1, 0, 1}.
> compareValues return values:
> =C2=A0 -1 =C2=A0=E2=86=92 less than
> =C2=A0 =C2=A00 =C2=A0=E2=86=92 equal
> =C2=A0 =C2=A01 =C2=A0=E2=86=92 greater than
> =C2=A0 =C2=A02 =C2=A0=E2=86=92 INDETERMINATE (NaN)
> Buggy checks:
> =C2=A0 minInclusive: if (result =3D=3D -1) =E2=86=92 FAIL =C2=A0 misses I=
NDETERMINATE(2) =E2=86=92 NaN passes =E2=9C=97
> =C2=A0 maxInclusive: if (result =3D=3D 1) =C2=A0=E2=86=92 FAIL =C2=A0 mis=
ses INDETERMINATE(2) =E2=86=92 NaN passes =E2=9C=97
> UNAFFECTED FACETS
> -----------------
> minExclusive and maxExclusive are not affected as their inverted logic in=
cidentally catches=C2=A0
> INDETERMINATE(2):
> =C2=A0 minExclusive: if (result !=3D 1) =C2=A0=E2=86=92 FAIL =C2=A0 catch=
es -1, 0, and 2 =E2=9C=93
> =C2=A0 maxExclusive: if (result !=3D -1) =E2=86=92 FAIL =C2=A0 catches =
=C2=A00, 1, and 2 =E2=9C=93
> AFFECTED FACETS
> ---------------
> =C2=A0 xs:minInclusive on xs:double and xs:float
> =C2=A0 xs:maxInclusive on xs:double and xs:float
> FIX
> =E2=80=94
> Tighten acceptance condition to only pass on known-valid orderings:
> =C2=A0 minInclusive: reject if (result !=3D 1 && result !=3D 0)
> =C2=A0 maxInclusive: reject if (result !=3D -1 && result !=3D 0)
> =C2=A0
> {*}{*}PR: [fix: NaN bypasses minInclusive/maxInclusive facets by gdesrosi=
ers1805 =C2=B7 Pull Request #64 =C2=B7 apache/xerces-c|https://github.com/a=
pache/xerces-c/pull/64]
> =C2=A0
--
This message was sent by Atlassian Jira
(v8.20.10#820010)