From 19e96d37dbace53e37946dcd8efd9610dac90ae5 Mon Sep 17 00:00:00 2001 From: Vineeth Sai Date: Sun, 19 Jul 2026 08:59:35 -0700 Subject: [PATCH] Report oversized regex repeat count as invalid instead of crashing The "regex" format checker declared raises=re.error, but re.compile raises OverflowError (not an re.error subclass) when a repetition count is too large, e.g. "a{99999999999999}". That OverflowError escaped FormatChecker.check uncaught, crashing conforms()/iter_errors()/validate instead of reporting the string as an invalid regex, unlike every other malformed pattern which is caught via re.error. Declare raises=(re.error, OverflowError) so the oversized-repeat case is reported as an invalid regex like the rest. Add a regression test. --- CHANGELOG.rst | 5 +++++ jsonschema/_format.py | 2 +- jsonschema/tests/test_format.py | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f169513ce..b131ab285 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,8 @@ +v4.27.0 +======= + +* Report a string as an invalid ``regex`` format rather than crashing when it contains a syntactically valid but oversized repetition count (which makes ``re.compile`` raise ``OverflowError`` instead of ``re.error``). + v4.26.0 ======= diff --git a/jsonschema/_format.py b/jsonschema/_format.py index 62c0e4ee3..ca7b54515 100644 --- a/jsonschema/_format.py +++ b/jsonschema/_format.py @@ -413,7 +413,7 @@ def is_time(instance: object) -> bool: return is_datetime("1970-01-01T" + instance) -@_checks_drafts(name="regex", raises=re.error) +@_checks_drafts(name="regex", raises=(re.error, OverflowError)) def is_regex(instance: object) -> bool: if not isinstance(instance, str): return True diff --git a/jsonschema/tests/test_format.py b/jsonschema/tests/test_format.py index d829f9848..536fadfcf 100644 --- a/jsonschema/tests/test_format.py +++ b/jsonschema/tests/test_format.py @@ -80,6 +80,15 @@ def test_format_checkers_come_with_defaults(self): with self.assertRaises(FormatError): checker.check(instance="not-an-ipv4", format="ipv4") + def test_regex_format_rejects_overflowing_repeat_count(self): + # A syntactically valid but oversized repetition count makes + # re.compile raise OverflowError, which is not an re.error, so it + # must be declared alongside it or it escapes uncaught instead of + # being reported as an invalid regex. + checker = FormatChecker() + with self.assertRaises(FormatError): + checker.check(instance="a{99999999999999}", format="regex") + def test_repr(self): checker = FormatChecker(formats=()) checker.checks("foo")(lambda thing: True) # pragma: no cover