mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
freeze.py, extended for v3 and still reading only git history, file lists and fix diffs: - a file the advisory names without a function resolves to the function(s) the fix's diff changes at the vulnerable pin (maintainer's decision 2), recorded with its basis (advisory-named / resolved-from-fix-diff); a new helper inserted at file scope adds no site; - an inferred fix must change a declared site function, else the case drops; - a single-language population gets a strict benign proposal (PHP change, merges judged with all they bring in, pre-vulnerable history as fallback). All 15 cases verified, none dropped (pagible and podlove fixes confirmed). Nine sites in eight cases resolved from diffs; five benign proposals replaced by hand. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
"""freeze.py resolves an advisory's file-only site to the function the fix changes (population v3, decision 2).
|
|
|
|
The resolver reads PHP text only; it must not be fooled by braces in strings, comments or inline HTML, and a line
|
|
outside every function is `<global>`."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
SPEC = importlib.util.spec_from_file_location("freeze", Path(__file__).resolve().parents[1] / "benchmarks" / "independent" / "freeze.py")
|
|
freeze = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(freeze)
|
|
|
|
PHP = """<html>{ not code }</html>
|
|
<?php
|
|
// a comment with { brace
|
|
class Box
|
|
{
|
|
public function open($x)
|
|
{
|
|
$s = "}{ in a string";
|
|
return function ($y) { return $y; };
|
|
}
|
|
|
|
abstract protected function shape();
|
|
|
|
private static function &close() {
|
|
/* } */
|
|
return <<<EOT
|
|
} heredoc {
|
|
EOT;
|
|
}
|
|
}
|
|
$top = 1;
|
|
?>
|
|
<div>{</div>
|
|
<?php function helper() { return '#{'; }
|
|
"""
|
|
|
|
|
|
def test_named_functions_and_their_lines() -> None:
|
|
spans = {name: (first, last) for name, first, last in freeze.php_functions(PHP)}
|
|
assert spans == {"open": (6, 10), "close": (14, 19), "helper": (24, 24)}
|
|
|
|
|
|
def test_a_line_resolves_to_its_innermost_named_function_or_global() -> None:
|
|
spans = freeze.php_functions(PHP)
|
|
assert freeze.enclosing(spans, 9) == "open" # inside the closure: the named function owns it
|
|
assert freeze.enclosing(spans, 17) == "close"
|
|
assert freeze.enclosing(spans, 21) == "<global>"
|
|
assert freeze.enclosing(spans, 1) == "<global>"
|
|
|
|
|
|
def test_an_insertion_after_a_closing_brace_is_outside_the_function() -> None:
|
|
spans = freeze.php_functions(PHP)
|
|
assert freeze.enclosing(spans, 10) == "open" # a changed line on the closing brace
|
|
assert freeze.enclosing(spans, 10, inserted=True) == "<global>" # new code that follows it
|
|
assert freeze.enclosing(spans, 8, inserted=True) == "open"
|