mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
feat(model): let the project say what it ships, and rank that first
contributor-scan 2.10. Every one of libpng's twenty-five entry-point regions was a `main()` -- twenty-three under contrib/, plus example.c and pngtest.c -- and those regions carried the fifty interprocedural taint requests that dominated a 300s query phase. A library has no entry points, so entry-point-driven analysis had nothing to anchor to except its own example programs. The task said to derive this rather than hardcode `contrib/`, and a project already declares it. Makefile.am names installed targets in `lib_LTLIBRARIES` and `bin_PROGRAMS`, each target's `<target>_SOURCES` names its files, and `check_PROGRAMS`/`noinst_PROGRAMS` are automake's own word for "not installed" -- exactly the distinction wanted. Taking every `_SOURCES` would have called libpng's whole test suite shipped code, since contrib/libtests declares its sources the same way the library does. interprocedural regions 25 -> 1 taint query 300.1s -> 125.0s total query 311.9s -> 138.5s regions 121 -> 121, unchanged by design The surviving interprocedural region is contrib/tools/pngfix.c:main, which libpng genuinely installs. Two rules keep it honest. **Silence is not exclusion**: a project with no build file this can read gets None back and nothing changes, so vampi's numbers are untouched. **Not shipped is not unscanned**: those regions are still arbitrated function-locally, because a contributor editing a test must still get an answer -- what they lose is the expensive treatment and first claim on the budget. Entailed findings went 0 -> 3, and all three are false positives at contrib/gregbook/wpng.c:374, `strcpy(outname+len, ".png")`. It is safe: outname is char[256] and line 325 guards with `if ((len = strlen(inname)) > 250)`. They were not introduced so much as uncovered -- a different callDepth meant a different sink set, and the 26 fgets false positives were masking them. The structural cause is recorded as 2.12: c/injection and c/memory carry ZERO sanitizers, so no C flow can ever be discharged and every `argv -> strcpy` entails however carefully it is bounded. The discharge here is not a call but a guard that dominates the sink, which is precisely what dominance.sc already does for access control and is wired to that one family. Also adds Group 7, five tasks for stopping the same false positive twice. Two of today's three false-positive classes were one bug in three matchers -- `resolve` in `resolveUrl`, `user` in `users`, `gets` in `fgets` -- each fixed locally and each next one surviving because nobody carried the fix across. A model may group counter-examples by cause and draft an edit; only a split-respecting measurement may adopt one, because the predecessor's improve lever admitted shapes taught by the holdout pairs they then recovered and turned a -0.059 Youden into +0.059. Gates byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
co-authored by
Claude Opus 5
parent
67497c4d68
commit
6dc25d77e4
@@ -210,3 +210,31 @@ def test_a_module_body_is_not_offered_the_handler_families() -> None:
|
||||
assert "access_control" not in module.families
|
||||
assert "config_secrets" in module.families, "settings are exactly what module bodies carry"
|
||||
assert module.source == "module_scope"
|
||||
|
||||
|
||||
def test_a_project_that_declares_nothing_is_not_penalised() -> None:
|
||||
"""contributor-scan 2.10: silence is not exclusion.
|
||||
|
||||
`declared_sources` returns None for a repository with no build files this can read, and every region
|
||||
stays shipped. A tool that quietly deprioritised code because it could not parse a Makefile would be
|
||||
worse than one that ignores the question.
|
||||
"""
|
||||
from openultrasast.model.regions import regions_for
|
||||
|
||||
regions = regions_for([_entry()], [_target()], shipped=None)
|
||||
|
||||
assert all(region.shipped for region in regions)
|
||||
|
||||
|
||||
def test_what_the_project_does_not_ship_ranks_below_what_it_does() -> None:
|
||||
"""libpng's twenty-five entry points were all `main()` in example programs and test tools."""
|
||||
from openultrasast.model.regions import regions_for
|
||||
|
||||
entries = [_entry(path="lib.py", function="handler", access="public"), _entry(path="example.py", function="main", access="public")]
|
||||
targets = [_target(path="lib.py"), _target(path="example.py")]
|
||||
|
||||
regions = regions_for(entries, targets, shipped=frozenset({"lib.py"}))
|
||||
|
||||
ordered = [(r.path, r.shipped) for r in regions]
|
||||
assert ordered[0] == ("lib.py", True), "shipped code comes first whatever the rank says"
|
||||
assert ("example.py", False) in ordered, "not shipped is not unscanned"
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
"""contributor-scan 2.10: what a project declares it ships, read from its own build files."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
MAKEFILE_AM = """\
|
||||
check_PROGRAMS= pngtest pngvalid
|
||||
bin_PROGRAMS= pngfix
|
||||
lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@[email protected]
|
||||
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\\
|
||||
\tpngget.c png.h
|
||||
|
||||
pngtest_SOURCES = contrib/libtests/pngtest.c
|
||||
pngvalid_SOURCES = contrib/libtests/pngvalid.c
|
||||
pngfix_SOURCES = contrib/tools/pngfix.c
|
||||
"""
|
||||
|
||||
|
||||
def test_only_installed_targets_count_as_shipped(tmp_path: Path) -> None:
|
||||
"""`check_PROGRAMS` declare their sources exactly as the library does, and are automake's own word for
|
||||
"not installed". Taking every `_SOURCES` would call libpng's whole test suite shipped code."""
|
||||
from openultrasast.model.shipped import declared_sources
|
||||
|
||||
(tmp_path / "Makefile.am").write_text(MAKEFILE_AM)
|
||||
for name in ("png.c", "pngerror.c", "pngget.c", "png.h"):
|
||||
(tmp_path / name).touch()
|
||||
|
||||
declared = declared_sources(tmp_path)
|
||||
|
||||
assert declared is not None
|
||||
assert {"png.c", "pngerror.c", "pngget.c", "png.h"} <= declared, "the library, across a continuation"
|
||||
assert "contrib/tools/pngfix.c" in declared, "bin_PROGRAMS is installed"
|
||||
assert "contrib/libtests/pngtest.c" not in declared, "check_PROGRAMS is not"
|
||||
assert "contrib/libtests/pngvalid.c" not in declared
|
||||
|
||||
|
||||
def test_a_repository_with_no_readable_build_files_declares_nothing(tmp_path: Path) -> None:
|
||||
"""None, not an empty set: the difference between "declares nothing" and "declares no sources"."""
|
||||
from openultrasast.model.shipped import declared_sources
|
||||
|
||||
(tmp_path / "app.py").write_text("x = 1\n")
|
||||
|
||||
assert declared_sources(tmp_path) is None
|
||||
|
||||
|
||||
def test_cmake_targets_are_read_and_their_keywords_are_not_files(tmp_path: Path) -> None:
|
||||
from openultrasast.model.shipped import declared_sources
|
||||
|
||||
(tmp_path / "CMakeLists.txt").write_text("add_library(png SHARED png.c png.h)\ntarget_sources(png PRIVATE extra.c)\n")
|
||||
|
||||
declared = declared_sources(tmp_path)
|
||||
|
||||
assert declared == frozenset({"png.c", "png.h", "extra.c"})
|
||||
|
||||
|
||||
def test_build_time_substitutions_are_skipped(tmp_path: Path) -> None:
|
||||
"""`$(wildcard ...)` and `@VERSION@` expand at build time; guessing at them would invent files."""
|
||||
from openultrasast.model.shipped import declared_sources
|
||||
|
||||
(tmp_path / "CMakeLists.txt").write_text("add_library(x STATIC ${GENERATED}.c real.c @[email protected] *.c)\n")
|
||||
|
||||
assert declared_sources(tmp_path) == frozenset({"real.c"})
|
||||
Reference in New Issue
Block a user