reject exponent notation in lexDecimal#63
Conversation
|
Again, this is too big a risk in a 20 year old lib. Can we at least have a XmlOptions setting? |
|
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. |
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.