test(r2): commit the round's falsifiers as a mutation table; one flag predicate
tests/mutations/r2_flow.toml: 18 falsifiers, each proved RED under its change by scripts/mutation_check.py (18/18). Its first run found three vacuous proofs, now resolved: - landed_at's per-entry skip: the symlink-loop fixture stopped raising once the clock moved to lstat. New fixture: a folder that lists but cannot be searched. - the Desk's bench URL guard: the test covered bookmarks only. A hand-edited registry bench now rides with it. - flagged_targets' `error is None`: defence in depth (hydration already strips a damaged mark's target), so no single-guard row; named in the table header instead. The rail's flagged filter and the orphan-flag list read flagged_targets rather than restating it; no reachable behaviour changes.
This commit is contained in:
@@ -759,6 +759,33 @@ def test_the_content_clock_reads_the_booth_not_what_its_links_point_at(tmp_path)
|
||||
assert _desk(c.get("/").text).get("rest") == ["g"]
|
||||
|
||||
|
||||
|
||||
def test_one_unreadable_entry_costs_that_entry_not_the_booth(tmp_path):
|
||||
"""Nyx (groa): one entry the walk can list but not stat made the whole
|
||||
booth read as landed NOW on every load, pinned in 'new' forever. A
|
||||
directory readable but not searchable is that entry: its names list, and
|
||||
every lstat under it is EACCES. (The symlink loop that first showed this
|
||||
stopped being a fixture for it once the clock moved to lstat, which reads
|
||||
a loop without following it.)"""
|
||||
import os
|
||||
t0 = time.time() - 10_000
|
||||
b = _booth(tmp_path, "g", {"a.png": PNG})
|
||||
sub = b / "d"
|
||||
sub.mkdir()
|
||||
(sub / "x.png").write_bytes(PNG)
|
||||
for p in (b / "a.png", sub / "x.png", sub):
|
||||
_at(p, t0)
|
||||
_at(b, t0)
|
||||
c = _client(tmp_path)
|
||||
c.get("/b/g/") # look at it
|
||||
sub.chmod(0o644) # r--: listable, nothing inside stat-able
|
||||
try:
|
||||
with pytest.raises(PermissionError):
|
||||
(sub / "x.png").lstat() # the fixture is live, not assumed
|
||||
assert _desk(c.get("/").text).get("rest") == ["g"]
|
||||
finally:
|
||||
sub.chmod(0o755)
|
||||
|
||||
def test_a_nul_in_the_review_path_is_a_404_not_a_500(tmp_path):
|
||||
"""Nyx (groa, seat-probed): Path raises ValueError on an embedded NUL, and
|
||||
the route caught only OSError. Every other hostile `f` is a 404."""
|
||||
@@ -789,11 +816,20 @@ def test_the_desk_never_makes_a_non_web_url_clickable(tmp_path):
|
||||
"""Nyx (kimi): bookmark and bench URLs are agent-written and land in href.
|
||||
Autoescape does nothing about a `javascript:` scheme. The Desk links only
|
||||
http(s) and shows anything else as plain text."""
|
||||
import json
|
||||
rows = (_link("evil", "javascript:alert`1`")
|
||||
+ _link("fine", "https://example.test/"))
|
||||
board = _booth(tmp_path, "links", {"links.md": rows.encode()})
|
||||
(board / ".forever").write_bytes(b"")
|
||||
# The bench WRITE path refuses a non-web URL; a hand-edited registry does
|
||||
# not pass through it, and the reader takes any text.
|
||||
(tmp_path / ".benches.json").write_text(json.dumps({
|
||||
"evil": {"url": "javascript:alert(1)", "name": "evil bench"},
|
||||
"http://h:1/": {"url": "http://h:1/", "name": "fine bench"}}))
|
||||
body = _client(tmp_path).get("/").text
|
||||
panel = re.search(r'data-panel="bookmarks".*?</section>', body, re.S).group(0)
|
||||
assert 'href="javascript:' not in panel
|
||||
assert 'href="https://example.test/"' in panel and "evil" in panel
|
||||
benches = re.search(r'data-panel="benches".*?</section>', body, re.S).group(0)
|
||||
assert 'href="javascript:' not in benches
|
||||
assert 'href="http://h:1/"' in benches and "evil bench" in benches
|
||||
|
||||
Reference in New Issue
Block a user