Create pipeline for symbol reachability - #2151
Conversation
944dcbe to
da128db
Compare
|
The pipeline requires the unidiff dependency to parse diffs/patch text |
d5fed3d to
08512ab
Compare
|
This depends on: We have an API support for patching VulnerableCode, see: |
3686a85 to
dfbb4db
Compare
|
I'm also not sure why Run unit tests on macOS / run-unit-tests (3.13) is failing. |
|
@ziadhany try to fix the failing test please |
| data = { | ||
| "purls": purls, | ||
| "details": True, | ||
| "reachability": True, |
There was a problem hiding this comment.
You should only go for reachability if collect_symbols_reachability has called it, not for every VCIO call
There was a problem hiding this comment.
We're currently relying on the find_vulnerabilities pipeline to retrieve vulnerabilities. One possible solution is to introduce an optional field reachability in the find_vulnerabilities pipeline.
|
@ziadhany this mostly looks good, let's have a session soon and do a demo and understand the limitations of the current approach |
| "urllib3==2.7.0", | ||
| "idna==3.16", | ||
| "GitPython==3.1.50", | ||
| "unidiff==0.7.5", |
There was a problem hiding this comment.
Is this absolutely needed? No built-in solutions available?
There was a problem hiding this comment.
The unidiff library doesn't have any dependencies, and we only need a single file from it: patch.py.
I'll include it in this PR files and add .ABOUT and .LICENSE files for it.
There was a problem hiding this comment.
Sorry, I phrased my question badly. I wasn't asking whether unidiff is dependency-free, I was asking whether we need to parse a unified diff in the first place.
We already have both file contents from the git trees in get_changed_files(), so difflib can give us the changed line numbers directly:
def compute_changed_lines(vulnerable_text, fixed_text):
"""Return the removed and added line numbers between two file contents."""
matcher = difflib.SequenceMatcher(
a=vulnerable_text.splitlines(),
b=fixed_text.splitlines(),
autojunk=False, # otherwise difflib ignores lines that repeat often
)
removed_lines = []
added_lines = []
for tag, vuln_start, vuln_end, fixed_start, fixed_end in matcher.get_opcodes():
if tag == "equal":
continue
# opcodes are 0-based and end-exclusive, line numbers are 1-based
removed_lines.extend(range(vuln_start + 1, vuln_end + 1))
added_lines.extend(range(fixed_start + 1, fixed_end + 1))
return removed_lines, added_linesIn collect_patch_symbols() this would replace a single line:
removed_lines, added_lines = compute_changed_lines(vulnerable_text, fixed_text)Would that work as a full replacement for unidiff? I'd rather avoid a vendored copy.
There was a problem hiding this comment.
You are right, we can use difflib.SequenceMatcher. I didn't notice there was a simpler solution.
6768aa8 to
577d4be
Compare
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Fix the test Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Add missing logic for imports Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Improve pipeline structure Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Fix formating tests Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Fix formating Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Fix a bug in extract_imports Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Get the dependency file and included in the PR Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
Fix a bug related to constant detections and add a test Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1555040 to
27de9f1
Compare
Issues
Changes
Add Pipeline(s) that can retrieve vulnerable / fix symbols, collect local symbols (pur2sym) and match them
Pipeline Graph:
flowchart TD %% Main Entry Point Start([collect_and_store_symbol_reachability_results]) --> GetResources[Filter candidate_resources] GetResources --> GroupPatches[Group fixed_in_patches by vcs_url] GroupPatches --> RepoLoop{For each repository} %% Repository Processing RepoLoop -->|Process Repo| GitContext[GitRepositoryContext] GitContext -->|Clone & Enter| PatchLoop{For each patch} %% Patch Processing PatchLoop -->|Next Patch| GitCheckout[Checkout commit_hash] GitCheckout --> GenReport[generate_reachability_report] %% Patch Analysis Stage GenReport --> PatchAnalyzer[PatchAnalyzer.collect_patch_symbols] PatchAnalyzer --> AnalyzeDiff[Get Diff & Changed Files] AnalyzeDiff --> PatchAnalyzeLoop[Analyze vulnerable & fixed texts] PatchAnalyzeLoop --> DetectLang[detect_language_with_scancode] DetectLang --> ParsePatchAST[LanguageQuery.parse_code_to_ast] ParsePatchAST --> ExtractPatchSymbols[SymbolExtractor: Extract Changed Symbols] ExtractPatchSymbols --> DiffSymbols[diff_changed_symbols] DiffSymbols --> ResourceLoop{For each candidate_resource} %% Resource Matching Stage ResourceLoop -->|Next Resource| LangCheck{Language matches patch?} LangCheck -->|No| ResourceLoop LangCheck -->|Yes| ResAnalyzer[ResourceAnalyzer.build_index] ResAnalyzer --> ParseResAST[Parse Resource to AST] ParseResAST --> IndexResSymbols[Extract definitions, imports, calls] IndexResSymbols --> Matcher[ResourcePatchMatcher.match] Matcher --> MatchVuln[Match Vulnerable Symbols] Matcher --> MatchFixed[Match Fixed Symbols] MatchVuln & MatchFixed --> CheckEvidence{Evidence found?} CheckEvidence -->|No| ResourceLoop %% Reporting Stage CheckEvidence -->|Yes| Classify[classify_reachability] Classify --> StatusReach[REACHABLE / POTENTIALLY / NOT_REACHABLE] StatusReach --> UpdateData[Update resource.extra_data] UpdateData --> ResourceLoop %% Loop Backs and Exit ResourceLoop -->|All resources checked| PatchLoop PatchLoop -->|All patches checked| RepoLoop RepoLoop -->|All repos checked| End([End Process]) %% Styling classDef functionNode fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px; classDef logicNode fill:#fff3e0,stroke:#ff9800,stroke-width:2px; classDef loopNode fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px; class Start,GenReport,PatchAnalyzer,ResAnalyzer,Matcher,Classify functionNode; class RepoLoop,PatchLoop,ResourceLoop loopNode; class LangCheck,CheckEvidence logicNode;Checklist