mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
fix(scan): a census gap that names its missing files is owned by those files
The first independent evaluation (results-v1.json) completed no question on eight of eleven projects. On the cases traced, the cause was a census gap: `.eslintrc.js` or `webpack.config.js` missing from a JavaScript graph, or `contrib/apache/api.wsgi` from a Python graph, and every question in that language was then marked unresolved. Now only questions about a named missing file are demoted. The gap is still reported as a boundary. A gap that names no files still reaches its whole partition. This is a retune after the evaluation. Per protocol-v1 it cannot be qualified on the same population. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
98e8dcdfb2
commit
dbcb230990
@@ -388,3 +388,48 @@ def test_only_a_request_entry_treats_its_parameters_as_attacker_input() -> None:
|
||||
assert params["1"]["parameterSources"] == "false"
|
||||
# Still followed into its callees: only its own parameters stop being sources.
|
||||
assert params["1"]["callDepth"] == params["0"]["callDepth"] != "0"
|
||||
|
||||
|
||||
class _CensusGapBackend(Backend):
|
||||
"""A graph whose census reads only some of its files, or reports no file names at all."""
|
||||
|
||||
def __init__(self, observed, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.observed = observed
|
||||
|
||||
def build(self, root, **kwargs):
|
||||
graph = super().build(root, **kwargs)
|
||||
inner = graph.run_batch
|
||||
|
||||
def batch(kind, requests):
|
||||
answer = dict(inner(kind, requests))
|
||||
row = {"methods": "3", "files": "2"}
|
||||
if self.observed is not None:
|
||||
row["file_names"] = list(self.observed)
|
||||
answer["__census__"] = [row]
|
||||
return answer
|
||||
|
||||
graph.run_batch = batch
|
||||
return graph
|
||||
|
||||
|
||||
def test_a_named_missing_file_demotes_only_the_questions_about_it(tmp_path):
|
||||
"""The first evaluation on untouched code completed no question on eight of eleven projects: a missing
|
||||
`.eslintrc.js` or `api.wsgi` made every question of its language unresolved. A missing file makes the
|
||||
graph incomplete about THAT file; an answer about another file is still an answer."""
|
||||
root = source(tmp_path, "app.py", "broken.py")
|
||||
evidence = {"app.py": vector(), "broken.py": vector()}
|
||||
regions = [region("app.py", "python"), region("broken.py", "python")]
|
||||
result = scan_repository(root, regions, backend=_CensusGapBackend(["app.py"], evidence=evidence), population_complete=True)
|
||||
status = {o.identity.path: (o.status, o.reason) for o in result.question_outcomes}
|
||||
assert status["broken.py"] == ("unresolved", "graph_incomplete"), status
|
||||
assert status["app.py"][0] == "completed", status
|
||||
assert "partition_file_census_incomplete" in result.scope.unresolved_boundaries
|
||||
|
||||
|
||||
def test_a_census_gap_that_names_no_file_still_reaches_its_partition(tmp_path):
|
||||
root = source(tmp_path, "app.py", "other.py")
|
||||
evidence = {"app.py": vector(), "other.py": vector()}
|
||||
regions = [region("app.py", "python"), region("other.py", "python")]
|
||||
result = scan_repository(root, regions, backend=_CensusGapBackend(None, evidence=evidence), population_complete=True)
|
||||
assert all(o.status == "unresolved" for o in result.question_outcomes), [(o.status, o.reason) for o in result.question_outcomes]
|
||||
|
||||
Reference in New Issue
Block a user