Commit dc96e45
committed
Stop uuid() from accepting urn:/braced forms via dead-code fallback
`uuid()` parsed input with the stdlib `UUID()` constructor and fell back
to a strict regex only "if UUID(value) is falsy":
return UUID(value) or re.match(r"^[0-9a-fA-F]{8}-...$", value)
A successfully-constructed `UUID` object is always truthy (it defines no
`__bool__`/`__len__`), so the `or re.match(...)` branch can never run.
In practice this means the actual acceptance criteria was "whatever
Python's UUID() constructor accepts", not the regex the code appears to
enforce -- and UUID() accepts considerably more than this validator
documents or tests, e.g.:
>>> uuid('urn:uuid:2bc1c94f-0deb-43e9-92a1-4775189ec9f8')
True # should be rejected
>>> uuid('{2bc1c94f-0deb-43e9-92a1-4775189ec9f8}')
True # should be rejected
Neither form appears in the docstring, the tests, or any prior issue/PR
I could find (checked via GitHub search for "uuid" -- the closest,
#112/#175, are about supporting hyphen-less hex, which this fix keeps
working).
Fix: drop the UUID()-based parsing entirely and validate with the regex
directly, extended to also accept the already-tested hyphen-less form.
This is a strict subset of what the old code intended to accept (per
its own regex and docstring), a superset check would have been
speculative; verified nothing currently-valid becomes invalid.
Verification:
- All 8 existing `test_uuid.py` cases still pass.
- Added 2 regression cases (`urn:uuid:...`, `{...}`) to the existing
invalid-input parametrize list; confirmed they fail against the
unpatched code (reverted locally to check) and pass with the fix.
- Non-string inputs (int, float, bool, list, dict, None) still resolve
to `ValidationError` rather than crashing -- `TypeError` from
`re.match` on a non-string is already caught by the `@validator`
decorator in `utils.py`, so no new exception handling was needed.
- Full suite: `pytest tests/` -- 897 passed (895 baseline + 2 new).
- `pytest --doctest-modules src/validators/` -- 57 passed, doctest for
`uuid` unaffected.
- `ruff format --check`, `ruff check`, and `pyright` all clean on the
changed files (matches this repo's `pycqa.yaml` CI job exactly).
Found via targeted review of validator internals after differential
fuzzing across the library's public functions, not from a filed issue.
AI-assisted (Code Puppy); reproduced, root-caused, fixed, and verified
against both the old and new code before opening this.1 parent 70de324 commit dc96e45
2 files changed
Lines changed: 13 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
35 | 42 | | |
36 | 43 | | |
37 | 44 | | |
| |||
0 commit comments