@@ -51,43 +51,40 @@ impl AlgorithmDetector {
5151 scan_path : & Path ,
5252 findings : & [ Finding ] ,
5353 ) -> Result < Vec < CryptoAsset > > {
54+ let registry = match & self . registry {
55+ Some ( registry) => registry,
56+ None => return Ok ( Vec :: new ( ) ) ,
57+ } ;
58+
5459 let mut algorithms = Vec :: new ( ) ;
5560 let mut seen_algorithms = HashSet :: new ( ) ;
5661
57- if let Some ( registry) = & self . registry {
58- // Extract algorithms from findings using registry patterns
59- for finding in findings {
60- if let Some ( algorithm_assets) =
61- self . extract_algorithms_from_finding_with_registry ( finding, registry) ?
62- {
63- for asset in algorithm_assets {
64- let key = self . create_deduplication_key ( & asset) ;
65- if seen_algorithms. insert ( key) {
66- algorithms. push ( asset) ;
67- }
68- }
69- }
70- }
71-
72- // Only perform deep static analysis if we have a reasonable number of findings
73- // Skip for large codebases to avoid performance issues
74- if findings. len ( ) < 1000 {
75- let additional_algorithms =
76- self . perform_deep_static_analysis_with_registry ( scan_path, registry) ?;
77- for asset in additional_algorithms {
62+ // Extract algorithms from findings using registry patterns
63+ for finding in findings {
64+ if let Some ( algorithm_assets) =
65+ self . extract_algorithms_from_finding_with_registry ( finding, registry) ?
66+ {
67+ for asset in algorithm_assets {
7868 let key = self . create_deduplication_key ( & asset) ;
7969 if seen_algorithms. insert ( key) {
8070 algorithms. push ( asset) ;
8171 }
8272 }
8373 }
84- } else {
85- // No registry available; skip instead of using static fallbacks.
74+ }
75+
76+ // Always perform deep static analysis regardless of findings count
77+ let additional_algorithms =
78+ self . perform_deep_static_analysis_with_registry ( scan_path, registry) ?;
79+ for asset in additional_algorithms {
80+ let key = self . create_deduplication_key ( & asset) ;
81+ if seen_algorithms. insert ( key) {
82+ algorithms. push ( asset) ;
83+ }
8684 }
8785
8886 // Merge duplicate algorithms with different parameter specificity
89- let merged_algorithms = self . merge_algorithm_assets ( algorithms) ;
90- Ok ( merged_algorithms)
87+ Ok ( self . merge_algorithm_assets ( algorithms) )
9188 }
9289
9390 /// Extract algorithms from finding using pattern registry
@@ -119,7 +116,7 @@ impl AlgorithmDetector {
119116 parameters,
120117 Some ( finding. library . clone ( ) ) ,
121118 Some ( AssetEvidence {
122- file : finding. file . display ( ) . to_string ( ) ,
119+ file : finding. file . to_string_lossy ( ) . to_string ( ) ,
123120 detector_id : finding. detector_id . clone ( ) ,
124121 line : finding. span . line ,
125122 column : finding. span . column ,
@@ -258,20 +255,18 @@ impl AlgorithmDetector {
258255 ) -> Result < Vec < CryptoAsset > > {
259256 let mut algorithms = Vec :: new ( ) ;
260257
261- // Only analyze a limited number of files to avoid performance issues
262- const MAX_FILES_TO_ANALYZE : usize = 100 ;
263- let mut files_analyzed = 0 ;
258+ // Analyze files for parameter extraction - removed arbitrary limits for comprehensive scanning
259+ let mut _files_analyzed = 0 ;
264260
265261 // Walk through source files for parameter extraction
266262 for entry in WalkDir :: new ( scan_path)
267- . max_depth ( 5 ) // Limit depth to avoid deep recursion
263+ . max_depth ( 20 ) // Support very deep directory structures
268264 . into_iter ( )
269265 . filter_map ( |e| e. ok ( ) )
270266 . filter ( |e| e. file_type ( ) . is_file ( ) )
271267 {
272- if files_analyzed >= MAX_FILES_TO_ANALYZE {
273- break ; // Stop after analyzing enough files
274- }
268+ // Note: Removed MAX_FILES_TO_ANALYZE limit for comprehensive cryptographic analysis
269+ // In large codebases, crypto usage can be deeply nested and limits can miss important findings
275270
276271 let path = entry. path ( ) ;
277272
@@ -285,7 +280,7 @@ impl AlgorithmDetector {
285280 ) {
286281 if let Ok ( mut extracted) = self . analyze_file_with_registry ( path, registry) {
287282 algorithms. append ( & mut extracted) ;
288- files_analyzed += 1 ;
283+ _files_analyzed += 1 ;
289284 }
290285 }
291286 }
@@ -373,18 +368,33 @@ impl AlgorithmDetector {
373368 Ok ( algorithms)
374369 }
375370
376- /// Create a proper deduplication key based on algorithm properties, not bom_ref
371+ /// Create a deduplication key based on algorithm properties AND evidence location
372+ /// This ensures same algorithms from different files are reported separately
377373 fn create_deduplication_key ( & self , asset : & CryptoAsset ) -> String {
378374 match & asset. asset_properties {
379375 AssetProperties :: Algorithm ( props) => {
380- // Deduplicate by algorithm name, primitive, and source library to avoid merging
381- // different libraries' detections of the same algorithm (e.g., OpenSSL vs CommonCrypto).
376+ // Include evidence location to allow multiple instances from different files/locations
382377 let library = asset. source_library . as_deref ( ) . unwrap_or ( "unknown-library" ) ;
378+ let params_key = props
379+ . parameter_set
380+ . as_ref ( )
381+ . map ( |p| format ! ( "{:?}" , p) )
382+ . unwrap_or_else ( || "no-params" . to_string ( ) ) ;
383+
384+ // Include file and line information to allow same algorithm from different locations
385+ let evidence_key = if let Some ( evidence) = & asset. evidence {
386+ format ! ( "{}:{}:{}" , evidence. file, evidence. line, evidence. column)
387+ } else {
388+ "no-evidence" . to_string ( )
389+ } ;
390+
383391 format ! (
384- "{}:{}:{}" ,
392+ "{}:{}:{}:{}:{} " ,
385393 asset. name. as_deref( ) . unwrap_or( "unknown" ) ,
386394 props. primitive as u8 ,
387- library
395+ library,
396+ params_key,
397+ evidence_key
388398 )
389399 }
390400 _ => format ! (
0 commit comments