Skip to content

Commit 3155940

Browse files
committed
Report regexes with oversized repeat counts as invalid, not an OverflowError
re.compile raises OverflowError (not an re.error subclass) when a repetition count is too large, e.g. 'a{99999999999999}'. The regex format checker declared raises=re.error only, so the exception escaped FormatChecker.check and propagated out of iter_errors/validate instead of reporting the string as an invalid regex (#1526). Declare OverflowError alongside re.error so it converts to a FormatError whose cause is the original exception.
1 parent 0abde23 commit 3155940

2 files changed

Lines changed: 23 additions & 2 deletions

File tree

‎jsonschema/_format.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ def is_time(instance: object) -> bool:
413413
return is_datetime("1970-01-01T" + instance)
414414

415415

416-
@_checks_drafts(name="regex", raises=re.error)
416+
@_checks_drafts(name="regex", raises=(re.error, OverflowError))
417417
def is_regex(instance: object) -> bool:
418418
if not isinstance(instance, str):
419419
return True

‎jsonschema/tests/test_format.py‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from jsonschema import FormatChecker, ValidationError
88
from jsonschema.exceptions import FormatError
9-
from jsonschema.validators import Draft4Validator
9+
from jsonschema.validators import Draft202012Validator, Draft4Validator
1010

1111
BOOM = ValueError("Boom!")
1212
BANG = ZeroDivisionError("Bang!")
@@ -71,6 +71,27 @@ def test_format_error_causes_become_validation_error_causes(self):
7171
self.assertIs(cm.exception.cause, BOOM)
7272
self.assertIs(cm.exception.__cause__, BOOM)
7373

74+
def test_oversized_repeat_regex_reports_invalid_not_overflow(self):
75+
# re.compile raises OverflowError (not an re.error subclass) when a
76+
# repetition count is too large, which must surface as a FormatError
77+
# rather than escape the checker (#1526).
78+
checker = FormatChecker(formats=["regex"])
79+
validator = Draft202012Validator(
80+
{"format": "regex"}, format_checker=checker,
81+
)
82+
pattern = "a{99999999999999}"
83+
84+
with self.assertRaises(FormatError):
85+
checker.check(pattern, "regex")
86+
87+
self.assertFalse(checker.conforms(pattern, "regex"))
88+
errors = list(validator.iter_errors(pattern))
89+
self.assertEqual(len(errors), 1)
90+
self.assertIsInstance(errors[0].cause, OverflowError)
91+
92+
# A sane bounded repeat still compiles and conforms.
93+
self.assertTrue(checker.conforms("a{2,4}", "regex"))
94+
7495
def test_format_checkers_come_with_defaults(self):
7596
# This is bad :/ but relied upon.
7697
# The docs for quite awhile recommended people do things like

0 commit comments

Comments
 (0)