execute checkers in the order they are registered

Summary:
This fixes a long-standing TODO. I re-ordered the lines by:
- first putting each entry on a single line (replacing "^J    " -> " "
  in emacs)
- then using emacs' M-x reverse-region
- then auto-formatting again

Reviewed By: skcho

Differential Revision: D21257475

fbshipit-source-id: 91b780a5d
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent 5580bc8901
commit 9a6cafe6ec

@ -28,18 +28,18 @@ type file_callback =
(** Place for storing issues generated at file-level analysis stage (additionally to ones (** Place for storing issues generated at file-level analysis stage (additionally to ones
generated by procedure-level callbacks which are stored in summaries) *) } generated by procedure-level callbacks which are stored in summaries) *) }
let procedure_callbacks = ref [] let procedure_callbacks_rev = ref []
let file_callbacks = ref [] let file_callbacks_rev = ref []
let register_procedure_callback ~checker_name ?(dynamic_dispatch = false) language let register_procedure_callback ~checker_name ?(dynamic_dispatch = false) language
(callback : proc_callback_t) = (callback : proc_callback_t) =
procedure_callbacks := procedure_callbacks_rev :=
{checker_name; dynamic_dispatch; language; callback} :: !procedure_callbacks {checker_name; dynamic_dispatch; language; callback} :: !procedure_callbacks_rev
let register_file_callback ~checker_name language (callback : file_callback_t) ~issue_dir = let register_file_callback ~checker_name language (callback : file_callback_t) ~issue_dir =
file_callbacks := {checker_name; language; callback; issue_dir} :: !file_callbacks file_callbacks_rev := {checker_name; language; callback; issue_dir} :: !file_callbacks_rev
let iterate_procedure_callbacks exe_env summary = let iterate_procedure_callbacks exe_env summary =
@ -58,8 +58,8 @@ let iterate_procedure_callbacks exe_env summary =
Option.value_map source_file ~default:[] ~f:SourceFiles.proc_names_of_source Option.value_map source_file ~default:[] ~f:SourceFiles.proc_names_of_source
in in
let is_specialized = Procdesc.is_specialized proc_desc in let is_specialized = Procdesc.is_specialized proc_desc in
List.fold ~init:summary List.fold_right ~init:summary !procedure_callbacks_rev
~f:(fun summary {checker_name; dynamic_dispatch; language; callback} -> ~f:(fun {checker_name; dynamic_dispatch; language; callback} summary ->
if Language.equal language procedure_language && (dynamic_dispatch || not is_specialized) then ( if Language.equal language procedure_language && (dynamic_dispatch || not is_specialized) then (
PerfEvent.( PerfEvent.(
log (fun logger -> log (fun logger ->
@ -70,11 +70,10 @@ let iterate_procedure_callbacks exe_env summary =
PerfEvent.(log (fun logger -> log_end_event logger ())) ; PerfEvent.(log (fun logger -> log_end_event logger ())) ;
summary ) summary )
else summary ) else summary )
!procedure_callbacks
let iterate_file_callbacks_and_store_issues procedures exe_env source_file = let iterate_file_callbacks_and_store_issues procedures exe_env source_file =
if not (List.is_empty !file_callbacks) then if not (List.is_empty !file_callbacks_rev) then
let environment = {procedures; source_file; exe_env} in let environment = {procedures; source_file; exe_env} in
let language_matches language = let language_matches language =
match procedures with match procedures with
@ -83,10 +82,8 @@ let iterate_file_callbacks_and_store_issues procedures exe_env source_file =
| _ -> | _ ->
true true
in in
List.iter List.iter (List.rev !file_callbacks_rev) ~f:(fun {language; callback; issue_dir} ->
~f:(fun {language; callback; issue_dir} ->
if language_matches language then ( if language_matches language then (
Language.curr_language := language ; Language.curr_language := language ;
let issue_log = callback environment in let issue_log = callback environment in
IssueLog.store ~file:source_file ~entry:issue_dir issue_log ) ) IssueLog.store ~file:source_file ~entry:issue_dir issue_log ) )
!file_callbacks

@ -28,58 +28,66 @@ type callback = callback_fun * Language.t
type checker = {name: string; active: bool; callbacks: callback list} type checker = {name: string; active: bool; callbacks: callback list}
let all_checkers = let all_checkers =
(* TODO (T24393492): the checkers should run in the order from this list. (* The order of the list is important for those checkers that depend on other checkers having run
Currently, the checkers are run in the reverse order *) before them. *)
[ { name= "annotation reachability" [ { name= "Self captured in block checker"
; active= Config.is_checker_enabled AnnotationReachability ; active= Config.is_checker_enabled SelfInBlock
; callbacks= [(Procedure SelfInBlock.checker, Language.Clang)] }
; { name= "Class loading analysis"
; active= Config.is_checker_enabled ClassLoads
; callbacks= [(Procedure ClassLoads.analyze_procedure, Language.Java)] }
; { name= "purity"
; active= Config.(is_checker_enabled Purity || is_checker_enabled LoopHoisting)
; callbacks= ; callbacks=
[ (Procedure AnnotationReachability.checker, Language.Java) [(Procedure Purity.checker, Language.Java); (Procedure Purity.checker, Language.Clang)] }
; (Procedure AnnotationReachability.checker, Language.Clang) ] } ; { name= "Starvation analysis"
; { name= "biabduction" ; active= Config.is_checker_enabled Starvation
; active= Config.is_checker_enabled Biabduction
; callbacks= ; callbacks=
[ (DynamicDispatch Interproc.analyze_procedure, Language.Clang) [ (Procedure Starvation.analyze_procedure, Language.Java)
; (DynamicDispatch Interproc.analyze_procedure, Language.Java) ] } ; (File {callback= Starvation.reporting; issue_dir= StarvationIssues}, Language.Java)
; { name= "buffer overrun analysis" ; (Procedure Starvation.analyze_procedure, Language.Clang)
; (File {callback= Starvation.reporting; issue_dir= StarvationIssues}, Language.Clang) ] }
; { name= "loop hoisting"
; active= Config.is_checker_enabled LoopHoisting
; callbacks=
[(Procedure Hoisting.checker, Language.Clang); (Procedure Hoisting.checker, Language.Java)]
}
; { name= "cost analysis"
; active= ; active=
Config.( Config.(
is_checker_enabled BufferOverrun || is_checker_enabled Cost is_checker_enabled Cost
|| is_checker_enabled LoopHoisting || is_checker_enabled Purity) || (is_checker_enabled LoopHoisting && hoisting_report_only_expensive))
; callbacks= ; callbacks= [(Procedure Cost.checker, Language.Clang); (Procedure Cost.checker, Language.Java)]
[ (Procedure BufferOverrunAnalysis.do_analysis, Language.Clang) }
; (Procedure BufferOverrunAnalysis.do_analysis, Language.Java) ] } ; { name= "uninitialized variables"
; { name= "buffer overrun checker" ; active= Config.is_checker_enabled Uninit
; active= Config.(is_checker_enabled BufferOverrun) ; callbacks= [(Procedure Uninit.checker, Language.Clang)] }
; callbacks= ; { name= "SIOF"
[ (Procedure BufferOverrunChecker.checker, Language.Clang) ; active= Config.is_checker_enabled SIOF
; (Procedure BufferOverrunChecker.checker, Language.Java) ] } ; callbacks= [(Procedure Siof.checker, Language.Clang)] }
; { name= "eradicate" ; { name= "litho-required-props"
; active= Config.is_checker_enabled Eradicate ; active= Config.is_checker_enabled LithoRequiredProps
; callbacks= [(Procedure RequiredProps.checker, Language.Java)] }
; (* toy resource analysis to use in the infer lab, see the lab/ directory *)
{ name= "resource leak"
; active= Config.is_checker_enabled ResourceLeak
; callbacks= ; callbacks=
[ (Procedure Eradicate.proc_callback, Language.Java) [ ( (* the checked-in version is intraprocedural, but the lab asks to make it
; (File {callback= Eradicate.file_callback; issue_dir= NullsafeFileIssues}, Language.Java) interprocedural later on *)
] } Procedure ResourceLeaks.checker
; { name= "fragment retains view" , Language.Java ) ] }
; active= Config.is_checker_enabled FragmentRetainsView ; { name= "RacerD"
; active= Config.is_checker_enabled RacerD
; callbacks= ; callbacks=
[(Procedure FragmentRetainsViewChecker.callback_fragment_retains_view, Language.Java)] } [ (Procedure RacerD.analyze_procedure, Language.Clang)
; { name= "immutable cast" ; (Procedure RacerD.analyze_procedure, Language.Java)
; active= Config.is_checker_enabled ImmutableCast ; (File {callback= RacerD.file_analysis; issue_dir= RacerDIssues}, Language.Clang)
; callbacks= [(Procedure ImmutableChecker.callback_check_immutable_cast, Language.Java)] } ; (File {callback= RacerD.file_analysis; issue_dir= RacerDIssues}, Language.Java) ] }
; { name= "inefficient keyset iterator" ; { name= "quandary"
; active= Config.is_checker_enabled InefficientKeysetIterator ; active= Config.(is_checker_enabled Quandary)
; callbacks= [(Procedure InefficientKeysetIterator.checker, Language.Java)] }
; { name= "liveness"
; active= Config.is_checker_enabled Liveness
; callbacks= [(Procedure Liveness.checker, Language.Clang)] }
; { name= "printf args"
; active= Config.is_checker_enabled PrintfArgs
; callbacks= [(Procedure PrintfArgs.callback_printf_args, Language.Java)] }
; { name= "impurity"
; active= Config.is_checker_enabled Impurity
; callbacks= ; callbacks=
[(Procedure Impurity.checker, Language.Java); (Procedure Impurity.checker, Language.Clang)] [ (Procedure JavaTaintAnalysis.checker, Language.Java)
} ; (Procedure ClangTaintAnalysis.checker, Language.Clang) ] }
; { name= "pulse" ; { name= "pulse"
; active= Config.(is_checker_enabled Pulse || is_checker_enabled Impurity) ; active= Config.(is_checker_enabled Pulse || is_checker_enabled Impurity)
; callbacks= ; callbacks=
@ -87,64 +95,56 @@ let all_checkers =
:: ::
( if Config.is_checker_enabled Impurity then [(Procedure Pulse.checker, Language.Java)] ( if Config.is_checker_enabled Impurity then [(Procedure Pulse.checker, Language.Java)]
else [] ) } else [] ) }
; { name= "quandary" ; { name= "impurity"
; active= Config.(is_checker_enabled Quandary) ; active= Config.is_checker_enabled Impurity
; callbacks= ; callbacks=
[ (Procedure JavaTaintAnalysis.checker, Language.Java) [(Procedure Impurity.checker, Language.Java); (Procedure Impurity.checker, Language.Clang)]
; (Procedure ClangTaintAnalysis.checker, Language.Clang) ] } }
; { name= "RacerD" ; { name= "printf args"
; active= Config.is_checker_enabled RacerD ; active= Config.is_checker_enabled PrintfArgs
; callbacks= [(Procedure PrintfArgs.callback_printf_args, Language.Java)] }
; { name= "liveness"
; active= Config.is_checker_enabled Liveness
; callbacks= [(Procedure Liveness.checker, Language.Clang)] }
; { name= "inefficient keyset iterator"
; active= Config.is_checker_enabled InefficientKeysetIterator
; callbacks= [(Procedure InefficientKeysetIterator.checker, Language.Java)] }
; { name= "immutable cast"
; active= Config.is_checker_enabled ImmutableCast
; callbacks= [(Procedure ImmutableChecker.callback_check_immutable_cast, Language.Java)] }
; { name= "fragment retains view"
; active= Config.is_checker_enabled FragmentRetainsView
; callbacks= ; callbacks=
[ (Procedure RacerD.analyze_procedure, Language.Clang) [(Procedure FragmentRetainsViewChecker.callback_fragment_retains_view, Language.Java)] }
; (Procedure RacerD.analyze_procedure, Language.Java) ; { name= "eradicate"
; (File {callback= RacerD.file_analysis; issue_dir= RacerDIssues}, Language.Clang) ; active= Config.is_checker_enabled Eradicate
; (File {callback= RacerD.file_analysis; issue_dir= RacerDIssues}, Language.Java) ] }
(* toy resource analysis to use in the infer lab, see the lab/ directory *)
; { name= "resource leak"
; active= Config.is_checker_enabled ResourceLeak
; callbacks= ; callbacks=
[ ( (* the checked-in version is intraprocedural, but the lab asks to make it [ (Procedure Eradicate.proc_callback, Language.Java)
interprocedural later on *) ; (File {callback= Eradicate.file_callback; issue_dir= NullsafeFileIssues}, Language.Java)
Procedure ResourceLeaks.checker ] }
, Language.Java ) ] } ; { name= "buffer overrun checker"
; { name= "litho-required-props" ; active= Config.(is_checker_enabled BufferOverrun)
; active= Config.is_checker_enabled LithoRequiredProps ; callbacks=
; callbacks= [(Procedure RequiredProps.checker, Language.Java)] } [ (Procedure BufferOverrunChecker.checker, Language.Clang)
; { name= "SIOF" ; (Procedure BufferOverrunChecker.checker, Language.Java) ] }
; active= Config.is_checker_enabled SIOF ; { name= "buffer overrun analysis"
; callbacks= [(Procedure Siof.checker, Language.Clang)] }
; { name= "uninitialized variables"
; active= Config.is_checker_enabled Uninit
; callbacks= [(Procedure Uninit.checker, Language.Clang)] }
; { name= "cost analysis"
; active= ; active=
Config.( Config.(
is_checker_enabled Cost is_checker_enabled BufferOverrun || is_checker_enabled Cost
|| (is_checker_enabled LoopHoisting && hoisting_report_only_expensive)) || is_checker_enabled LoopHoisting || is_checker_enabled Purity)
; callbacks= [(Procedure Cost.checker, Language.Clang); (Procedure Cost.checker, Language.Java)]
}
; { name= "loop hoisting"
; active= Config.is_checker_enabled LoopHoisting
; callbacks= ; callbacks=
[(Procedure Hoisting.checker, Language.Clang); (Procedure Hoisting.checker, Language.Java)] [ (Procedure BufferOverrunAnalysis.do_analysis, Language.Clang)
} ; (Procedure BufferOverrunAnalysis.do_analysis, Language.Java) ] }
; { name= "Starvation analysis" ; { name= "biabduction"
; active= Config.is_checker_enabled Starvation ; active= Config.is_checker_enabled Biabduction
; callbacks= ; callbacks=
[ (Procedure Starvation.analyze_procedure, Language.Java) [ (DynamicDispatch Interproc.analyze_procedure, Language.Clang)
; (File {callback= Starvation.reporting; issue_dir= StarvationIssues}, Language.Java) ; (DynamicDispatch Interproc.analyze_procedure, Language.Java) ] }
; (Procedure Starvation.analyze_procedure, Language.Clang) ; { name= "annotation reachability"
; (File {callback= Starvation.reporting; issue_dir= StarvationIssues}, Language.Clang) ] } ; active= Config.is_checker_enabled AnnotationReachability
; { name= "purity"
; active= Config.(is_checker_enabled Purity || is_checker_enabled LoopHoisting)
; callbacks= ; callbacks=
[(Procedure Purity.checker, Language.Java); (Procedure Purity.checker, Language.Clang)] } [ (Procedure AnnotationReachability.checker, Language.Java)
; { name= "Class loading analysis" ; (Procedure AnnotationReachability.checker, Language.Clang) ] } ]
; active= Config.is_checker_enabled ClassLoads
; callbacks= [(Procedure ClassLoads.analyze_procedure, Language.Java)] }
; { name= "Self captured in block checker"
; active= Config.is_checker_enabled SelfInBlock
; callbacks= [(Procedure SelfInBlock.checker, Language.Clang)] } ]
let get_active_checkers () = let get_active_checkers () =

Loading…
Cancel
Save