mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-20 05:29:28 +00:00
fix(hunt): label every verified target of a change; undo an inherited sparse-checkout in the worktree
label_rows honoured only a change's primary site, so 43 of the 48 accepted access-control locations were unlabelled; every entry of targets is now a positive with its own label_ref and span. The training clones were emptied with sparse-checkout to save disk and a new worktree inherits it: every file read failed and the source and semantic producers reported an unread tree on all 599 rows. The runner now disables sparse-checkout in the worktree it adds. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
30921a12b9
commit
499f6c4474
@@ -16,21 +16,30 @@ def label_rows(rows: Sequence[Mapping[str, Any]], change: Mapping[str, Any]) ->
|
|||||||
raise ValueError("a label needs a traceable case_id")
|
raise ValueError("a label needs a traceable case_id")
|
||||||
if kind == "vulnerability" and not all(change.get(k) for k in ("path", "function", "function_lines", "family")):
|
if kind == "vulnerability" and not all(change.get(k) for k in ("path", "function", "function_lines", "family")):
|
||||||
raise ValueError("a vulnerability label needs its path, function, span and family")
|
raise ValueError("a vulnerability label needs its path, function, span and family")
|
||||||
|
# Every verified site of the change is a positive: the primary one and, when several accepted
|
||||||
|
# locations share the fix commit, each entry of ``targets``.
|
||||||
|
sites = []
|
||||||
|
if kind == "vulnerability":
|
||||||
|
sites.append((change["path"], change["function"], list(change["function_lines"]), change["case_id"]))
|
||||||
|
for target in change.get("targets", []):
|
||||||
|
sites.append((target["path"], target["function"], list(target["function_lines"]), target.get("case_id", change["case_id"])))
|
||||||
result = []
|
result = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
data = deepcopy(dict(row))
|
data = deepcopy(dict(row))
|
||||||
span = change.get("function_lines")
|
|
||||||
function = row.get("function", row.get("feature.source.function"))
|
function = row.get("function", row.get("feature.source.function"))
|
||||||
site = (
|
matched = next(
|
||||||
kind == "vulnerability"
|
(
|
||||||
and row.get("path") == change["path"]
|
site
|
||||||
and (function == change["function"] or (span[0] <= row.get("line", 0) <= span[1]))
|
for site in sites
|
||||||
|
if row.get("path") == site[0] and (function == site[1] or (site[2][0] <= row.get("line", 0) <= site[2][1]))
|
||||||
|
),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
data.update(
|
data.update(
|
||||||
label=1 if site else 0 if kind == "ordinary" else None,
|
label=1 if matched else 0 if kind == "ordinary" else None,
|
||||||
family=change["family"] if site else None,
|
family=change["family"] if matched else None,
|
||||||
fix_span=list(span) if site else None,
|
fix_span=matched[2] if matched else None,
|
||||||
label_ref=change["case_id"] if site or kind == "ordinary" else None,
|
label_ref=matched[3] if matched else change["case_id"] if kind == "ordinary" else None,
|
||||||
verification=None,
|
verification=None,
|
||||||
)
|
)
|
||||||
result.append(data)
|
result.append(data)
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ def hunt_change(
|
|||||||
try:
|
try:
|
||||||
_git(repo_root, "worktree", "add", "--detach", str(root), change["head"])
|
_git(repo_root, "worktree", "add", "--detach", str(root), change["head"])
|
||||||
added = True
|
added = True
|
||||||
|
_full_checkout(root)
|
||||||
if _git(root, "rev-parse", "HEAD").strip() != change["head"]:
|
if _git(root, "rev-parse", "HEAD").strip() != change["head"]:
|
||||||
raise InstrumentFailure("head_mismatch")
|
raise InstrumentFailure("head_mismatch")
|
||||||
instrument["head_verified"] = True
|
instrument["head_verified"] = True
|
||||||
@@ -160,6 +161,19 @@ def hunt_change(
|
|||||||
return record
|
return record
|
||||||
|
|
||||||
|
|
||||||
|
def _full_checkout(root: Path) -> None:
|
||||||
|
"""Undo a sparse-checkout a worktree inherits from a clone whose working tree was emptied to save disk.
|
||||||
|
|
||||||
|
Without this every file read fails and the producers report an unread tree, which must never pass as a
|
||||||
|
clean result."""
|
||||||
|
try:
|
||||||
|
sparse = _git(root, "config", "--get", "core.sparseCheckout").strip()
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return
|
||||||
|
if sparse == "true":
|
||||||
|
_git(root, "sparse-checkout", "disable")
|
||||||
|
|
||||||
|
|
||||||
def _function_at(root: Path, finding: Mapping[str, Any]) -> str | None:
|
def _function_at(root: Path, finding: Mapping[str, Any]) -> str | None:
|
||||||
try:
|
try:
|
||||||
path = str(finding["path"])
|
path = str(finding["path"])
|
||||||
|
|||||||
@@ -45,3 +45,22 @@ def test_positive_requires_traceable_reference():
|
|||||||
del change["case_id"]
|
del change["case_id"]
|
||||||
with pytest.raises(ValueError, match="case_id"):
|
with pytest.raises(ValueError, match="case_id"):
|
||||||
label_rows([], change)
|
label_rows([], change)
|
||||||
|
|
||||||
|
|
||||||
|
def test_every_verified_target_of_a_change_is_a_positive():
|
||||||
|
change = {
|
||||||
|
**positive(),
|
||||||
|
"case_id": "c1",
|
||||||
|
"targets": [
|
||||||
|
{"case_id": "c1", "path": "app.py", "function": "handle", "function_lines": [10, 20]},
|
||||||
|
{"case_id": "c2", "path": "lib.py", "function": "check", "function_lines": [3, 8]},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
rows = [
|
||||||
|
{"path": "app.py", "line": 12, "function": "handle"},
|
||||||
|
{"path": "lib.py", "line": 5, "function": "check"},
|
||||||
|
{"path": "lib.py", "line": 40, "function": "other"},
|
||||||
|
]
|
||||||
|
out = label_rows(rows, change)
|
||||||
|
assert [r["label"] for r in out] == [1, 1, None]
|
||||||
|
assert out[1]["label_ref"] == "c2" and out[1]["fix_span"] == [3, 8] and out[2]["label_ref"] is None
|
||||||
|
|||||||
Reference in New Issue
Block a user