mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
fix(prover-arm): the byte table holds only files that were read, so a zero-byte read stays on the record and the summary refuses it
CI failed test_unchanged_file_empty_read_refuses: the previous fix skipped failed records in the zero-byte rule. Now the arm records a file's size only after reading it (a git-empty file is counted under empty_files and not listed), a real zero-byte read keeps its zero and the summary refuses it on every record as the test says. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
beb272a5ec
commit
5980bf8377
@@ -89,23 +89,18 @@ def _prove(change, repos, *, max_depth):
|
|||||||
if held.returncode == 0:
|
if held.returncode == 0:
|
||||||
raise InstrumentFailure("unread tracked file")
|
raise InstrumentFailure("unread tracked file")
|
||||||
continue # a file deleted by this change has no head input
|
continue # a file deleted by this change has no head input
|
||||||
instrument["file_bytes"][relative] = 0
|
|
||||||
if relative in changed:
|
|
||||||
instrument["changed_bytes"][relative] = 0
|
|
||||||
try:
|
try:
|
||||||
text = ctx.read(relative)
|
text = ctx.read(relative)
|
||||||
except _Absent as error:
|
except _Absent as error:
|
||||||
# A file git holds empty is read, not unread: the first smoke run failed four changes on
|
# A file git holds empty is read, not unread: the first smoke run failed four changes on
|
||||||
# legitimately empty files (`__init__.py`, an empty asset). Anything else absent is unread.
|
# legitimately empty files (`__init__.py`, an empty asset). Anything else absent is unread.
|
||||||
held = checked_git.runner(
|
held = checked_git.runner(["git", "-C", str(root), "cat-file", "-s", f"HEAD:{relative}"], capture_output=True, text=True)
|
||||||
["git", "-C", str(root), "cat-file", "-s", f"HEAD:{relative}"], capture_output=True, text=True
|
|
||||||
)
|
|
||||||
if error.reason == "empty_source" and held.returncode == 0 and int(held.stdout.strip() or 0) == 0:
|
if error.reason == "empty_source" and held.returncode == 0 and int(held.stdout.strip() or 0) == 0:
|
||||||
instrument["empty_files"] = instrument.get("empty_files", 0) + 1
|
instrument["empty_files"] = instrument.get("empty_files", 0) + 1
|
||||||
del instrument["file_bytes"][relative]
|
|
||||||
instrument["changed_bytes"].pop(relative, None)
|
|
||||||
continue
|
continue
|
||||||
raise InstrumentFailure("unread tracked file") from error
|
raise InstrumentFailure("unread tracked file") from error
|
||||||
|
# The byte table holds only files that were read; a zero here is a real zero-byte read, which
|
||||||
|
# stays on the record so the summary refuses it.
|
||||||
size = len(text.encode("utf-8"))
|
size = len(text.encode("utf-8"))
|
||||||
instrument["file_bytes"][relative] = size
|
instrument["file_bytes"][relative] = size
|
||||||
if relative in changed:
|
if relative in changed:
|
||||||
@@ -180,8 +175,6 @@ def summarize(out, *, seed=0):
|
|||||||
raise ValueError("missing or duplicate prover records")
|
raise ValueError("missing or duplicate prover records")
|
||||||
for record in records:
|
for record in records:
|
||||||
instrument = record.get("instrument", {})
|
instrument = record.get("instrument", {})
|
||||||
if record.get("status") == "instrument_failure":
|
|
||||||
continue # counted as a failure already; its byte table stops where the failure happened
|
|
||||||
if any(size == 0 for field in ("changed_bytes", "file_bytes") for size in instrument.get(field, {}).values()):
|
if any(size == 0 for field in ("changed_bytes", "file_bytes") for size in instrument.get(field, {}).values()):
|
||||||
raise ValueError("zero-byte read of a tracked file; summary refused")
|
raise ValueError("zero-byte read of a tracked file; summary refused")
|
||||||
result = metrics.summarize(records, seed=seed)
|
result = metrics.summarize(records, seed=seed)
|
||||||
|
|||||||
Reference in New Issue
Block a user