Skip to content

reject exponent notation in lexDecimal#63

Closed
aizu-m wants to merge 2 commits into
apache:trunkfrom
aizu-m:lexdecimal-reject-exponent
Closed

reject exponent notation in lexDecimal#63
aizu-m wants to merge 2 commits into
apache:trunkfrom
aizu-m:lexdecimal-reject-exponent

Conversation

@aizu-m

@aizu-m aizu-m commented Jun 20, 2026

Copy link
Copy Markdown
XsTypeConverter.lexDecimal("1E5") -> 100000

Spotted this comparing the rich parser path against the validating one. xsd:decimal has no exponent, so "1E5" is not a valid decimal, but lexDecimal passes the value straight to new BigDecimal which happily accepts scientific notation. JavaDecimalHolder.validateLexical already rejects a stray 'E', so the two paths disagree on the same value.

Reachable from untrusted XML through the rich parser getBigDecimalValue / getAttributeBigDecimalValue, which call lexDecimal and only expect a NumberFormatException for bad input. An exponent value therefore comes back as a wrong number (100000 above) rather than the documented lexical error.

Reject e/E in lexDecimal so parsing stays inside the decimal lexical space. Plain decimal forms are untouched. Regression test added in XsTypeConverterTest.

@pjfanning

Copy link
Copy Markdown
Member

Again, this is too big a risk in a 20 year old lib. Can we at least have a XmlOptions setting?
Default it to disallow e notation because e notation can be expensive to parse if the values have very high exponent values.
You should also check that this is applied to xs:integer parsing and any other lex methods where BigDecimal is used to parse the numbers.

@aizu-m

aizu-m commented Jun 20, 2026

Copy link
Copy Markdown
Author

Pushed. Default is still to disallow the exponent, but it's now behind XmlOptions.setLoadAllowDecimalExponent so it can be turned back on. Wired it the same way as setLoadStrictFloatingPoint: XmlLocale -> Locale -> the decimal holders, with lexDecimal(cs) strict by default and lexDecimal(cs, true) for the lenient parse.

Checked the integer side like you asked: xs:integer parses through new BigInteger, and that already throws on an exponent (new BigInteger("1E5") -> NumberFormatException), so both lexInteger and the integer holder reject it without any change. lexDecimal is the only lex method that builds a BigDecimal; float/double are meant to accept an exponent, so I left those alone.

Tests cover the strict default, the allow-exponent overload, the integer case, a load round-trip with the option set, and the flag itself. misc.checkin and the schematype/validation suites are green.

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