Skip to content

fix: NaN bypasses minInclusive/maxInclusive facets#64

Open
gdesrosiers1805 wants to merge 1 commit intoapache:masterfrom
gdesrosiers1805:bugfix/nan-min-max-inclussive-fix
Open

fix: NaN bypasses minInclusive/maxInclusive facets#64
gdesrosiers1805 wants to merge 1 commit intoapache:masterfrom
gdesrosiers1805:bugfix/nan-min-max-inclussive-fix

Conversation

@gdesrosiers1805
Copy link
Copy Markdown

@gdesrosiers1805 gdesrosiers1805 commented Apr 12, 2026

NaN silently passes bounds validation due to trichotomy failure in compareValues.

Root Cause:
- boundsCheck assumes trichotomy from compareValues (total order): -1, 0, or 1
- NaN triggers compareSpecial → returns 2 (INDETERMINATE)
- Trichotomy broken by 4th value (NaN)
- minInclusive: if (result == -1) → misses INDETERMINATE(2)
- maxInclusive: if (result == 1) → misses INDETERMINATE(2)

Affected: minInclusive/maxInclusive facets only
Unaffected: minExclusive/maxExclusive correctly detect NaN

Fix:
- minInclusive: reject (result != 1 && result != 0)
- maxInclusive: reject (result != -1 && result != 0)

@gdesrosiers1805
Copy link
Copy Markdown
Author

bug can be reproduced by running one of the provided sample programs SAX2COUNT with the following arguments:
SAX2Count -v=always -f testFileName. Test files have been updated here to show difference between inclusive and exclusive facets. below is the output of all 4 different tests files:

  1. SAX2Count -v=always -f test_minExclusive.xml

    Error at file test_minExclusive.xml, line 3, char 84
    Message: value 'NaN' must be greater than or equal to minExclusive facet value '0.0'

  2. SAX2Count -v=always -f test_minInclusive.xml
    test_minInclusive.xml: 1 ms (1 elems, 1 attrs, 0 spaces, 3 chars)

  3. SAX2Count -v=always -f test_maxExclusive.xml

    Error at file test_maxExclusive.xml, line 3, char 84
    Message: value 'NaN' must be less than maxExclusive facet value '100.0'

  4. SAX2Count -v=always -f test_maxInclusive.xml
    test_maxInclusive.xml: 0 ms (1 elems, 1 attrs, 0 spaces, 3 chars)

Note:This Bug was discovered in version 3.2.4 but was tested and found as well in latest release 3.3.0 as well.
test_maxExclusive.xml
test_maxInclusive.xml
test_minExclusive.xml
test_minInclusive.xml
NaN_maxExclusive.xsd.txt
NaN_maxInclusive.xsd.txt
NaN_minExclusive.xsd.txt
NaN_minInclusive.xsd.txt

@gdesrosiers1805 gdesrosiers1805 force-pushed the bugfix/nan-min-max-inclussive-fix branch from 969c52c to 0e526fe Compare April 12, 2026 15:35
NaN silently passes bounds validation due to trichotomy failure in compareValues.

Root Cause:
- boundsCheck assumes trichotomy from compareValues (total order): -1, 0, or 1
- NaN triggers compareSpecial → returns 2 (INDETERMINATE)
- Trichotomy broken by 4th value (NaN)
- minInclusive: `if (result == -1)` → misses INDETERMINATE(2)
- maxInclusive: `if (result == 1)` → misses INDETERMINATE(2)

Affected: minInclusive/maxInclusive facets only
Unaffected: minExclusive/maxExclusive correctly detect NaN

Fix:
- minInclusive: reject `(result != 1 && result != 0)`
- maxInclusive: reject `(result != -1 && result != 0)`
@gdesrosiers1805 gdesrosiers1805 force-pushed the bugfix/nan-min-max-inclussive-fix branch from 0e526fe to a5b837e Compare April 12, 2026 15:56
@gdesrosiers1805
Copy link
Copy Markdown
Author

According to git history this bug was introduced in commit:
f75e7f0

What Changed:

  • compareSpecial() updated for Schema Errata E2-40
  • NaN now returns 2 (INDETERMINATE) instead of 1

What Was Missed:

  • boundsCheck() never updated for new return value
  • Still assumes trichotomy
  • INDETERMINATE(2) silently ignored → NaN bypasses min/maxInclusive

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.

1 participant