fix(errors): type the NUL-byte path failure as SourceError
safe_resolve let an untyped ValueError escape when a target carried an
embedded NUL: os.path.realpath rejects the string before the boundary
check runs. That broke SourceError's documented contract ("always typed,
never a leaked OSError") and the v0.3.0 promise of stable machine-readable
codes on every failure.
A target that cannot be resolved at all now fails closed under the
existing `path_escape` code, with its own message. No new code is added —
`path_escape` already means "the boundary refused this target"; its
docstring is widened to say so. Consumers asserting on the code are
unaffected.
Found by consumer review: portfolio-optimiser's navigate_bundle leaks the
same ValueError from the same class of input, which makes an entire bundle
unreadable instead of skipping one link. That defect is theirs to fix; this
commit closes the library-side half.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WdVgowYC4LARgvNdNMiuvz
This commit is contained in:
parent
692f2df2ba
commit
64e3187639
3 changed files with 21 additions and 2 deletions
|
|
@ -157,6 +157,17 @@ def test_path_escape(tmp_path: Path) -> None:
|
|||
assert code_of(excinfo) == "path_escape"
|
||||
|
||||
|
||||
def test_path_escape_covers_embedded_null(tmp_path: Path) -> None:
|
||||
# A NUL byte makes the OS path syscalls raise ValueError before any
|
||||
# boundary check runs. SourceError promises "always typed, never a
|
||||
# leaked OSError" — an untyped ValueError breaks that contract, so a
|
||||
# malformed target must fail closed under the same code as any other
|
||||
# target that cannot resolve inside the root.
|
||||
with pytest.raises(SourceError) as excinfo:
|
||||
safe_resolve(tmp_path, "bad\x00.md")
|
||||
assert code_of(excinfo) == "path_escape"
|
||||
|
||||
|
||||
def test_source_root_missing(tmp_path: Path) -> None:
|
||||
with pytest.raises(SourceError) as excinfo:
|
||||
read_csv(tmp_path / "nope", "a.csv", max_rows=1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue