python-jsonschema / python-jsonschema/jsonschema

regex format checker crashes with ValueError on conflicting inline flags

Open
#1,558 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
5k
Forks
671
Avg merge
1d 1h
Merged PRs (30d)
10

Description

The regex format checker is registered with raises=re.error:

@_checks_drafts(name="regex", raises=re.error)
def is_regex(instance: object) -> bool:
    if not isinstance(instance, str):
        return True
    return bool(re.compile(instance))

FormatChecker.check only converts the declared exception into a FormatError. But re.compile raises ValueError (not an re.error subclass) when a pattern sets two incompatible inline flags, so the exception escapes uncaught and the format check crashes instead of reporting the string as an invalid regex.

Reproduction
from jsonschema import FormatChecker

fc = FormatChecker()

fc.conforms("[unterminated", "regex")   # False - re.error, caught correctly
fc.conforms("(?u)(?a)", "regex")        # ValueError: ASCII and UNICODE flags are incompatible

Also reproduces with the flags in the other order ("(?a)(?u)"). Note that "(?ua)" - both flags in a single group - returns False correctly, so this is specific to the two-group form.

Expected

"(?u)(?a)" is not a valid regular expression, so the instance should be reported as invalid, exactly like "[unterminated" is.

Cause

ValueError is not a subclass of re.error:

>>> import re
>>> issubclass(ValueError, re.error)
False
>>> re.error.__mro__
(<class 're.PatternError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)

so raises=re.error does not cover it.

Related

Same root cause as #1526 (OverflowError on an oversized repeat count) and #1538 (RecursionError on deep nesting) - three exception types, one declaration that only catches re.error.

There is a fourth case worth mentioning because it shows the set is not stable across CPython versions: "(?(1)a|b)" (a conditional) raised an uncaught RuntimeError on Python 3.9.6, but on 3.13 re.compile raises re.error for it and it is now handled correctly. So which exception types escape depends on the CPython release, not just on jsonschema.

Given three open issues with one cause, it may be worth widening what is_regex catches rather than adding types one at a time - re.compile does not document re.error as the only exception it can raise.

Versions

Reproduced on:

  • jsonschema 4.26.0, Python 3.13.11
  • jsonschema 4.25.1, Python 3.9.6

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the regex format checker and FormatChecker.check, then inspect the existing handling for re.error and the related issues #1526 and #1538. Add regression coverage for conflicting inline flags and the other reported escaping cases, and verify invalid patterns return False or a FormatError without an uncaught exception across supported Python versions.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.