The duration format check can raise decimal.Overflow instead of returning a result, so validating certain strings throws an uncaught exception rather than reporting the instance as invalid.
Versions
- jsonschema 4.25.1
- isoduration 20.11.0 (the optional dependency
is_duration delegates to)
- Python 3.9
Reproduction
from jsonschema import Draft202012Validator as V
from jsonschema import FormatChecker
v = V({"format": "duration"}, format_checker=FormatChecker())
list(v.iter_errors("P1E1000000D"))
raises:
decimal.Overflow: [<class 'decimal.Overflow'>]
Cause
_format.is_duration calls isoduration.parse_duration(instance) and is registered with raises=isoduration.DurationParsingException. isoduration parses each component amount with Decimal(...), and for an exponent past the decimal context's Emax (999999), Decimal("1E1000000") raises decimal.Overflow. That is not a subclass of DurationParsingException, so it propagates out of the format checker uncaught.
The boundary is exact: P1E999999D is accepted, P1E1000000D overflows. It is also reachable without an exponent, via a plain digit run longer than Emax.
Expected
The check should report the instance as invalid (P1E1000000D is not a valid RFC 3339 Appendix A duration - the grammar uses 1*DIGIT, with no exponent), not raise.
Possible fix
Either broaden what is_duration catches (add ArithmeticError / decimal.Overflow alongside DurationParsingException, or wrap the parse_duration call), or treat any exception from parse_duration as "not a duration".
The
durationformat check can raisedecimal.Overflowinstead of returning a result, so validating certain strings throws an uncaught exception rather than reporting the instance as invalid.Versions
is_durationdelegates to)Reproduction
raises:
Cause
_format.is_durationcallsisoduration.parse_duration(instance)and is registered withraises=isoduration.DurationParsingException. isoduration parses each component amount withDecimal(...), and for an exponent past the decimal context'sEmax(999999),Decimal("1E1000000")raisesdecimal.Overflow. That is not a subclass ofDurationParsingException, so it propagates out of the format checker uncaught.The boundary is exact:
P1E999999Dis accepted,P1E1000000Doverflows. It is also reachable without an exponent, via a plain digit run longer thanEmax.Expected
The check should report the instance as invalid (
P1E1000000Dis not a valid RFC 3339 Appendix A duration - the grammar uses1*DIGIT, with no exponent), not raise.Possible fix
Either broaden what
is_durationcatches (addArithmeticError/decimal.OverflowalongsideDurationParsingException, or wrap theparse_durationcall), or treat any exception fromparse_durationas "not a duration".