You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
5.5 KiB

(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** Module for registering checkers. *)
module L = Logging
module F = Format
(* make sure SimpleChecker.ml is not dead code *)
let () = if false then let module SC = SimpleChecker.Make in ()
type callback_fun =
| Procedure of Callbacks.proc_callback_t
| DynamicDispatch of Callbacks.proc_callback_t
| Cluster of Callbacks.cluster_callback_t
type callback = callback_fun * Language.t
type checker = {name: string; active: bool; callbacks: callback list}
let all_checkers =
(* TODO (T24393492): the checkers should run in the order from this list.
Currently, the checkers are run in the reverse order *)
[ { name= "annotation reachability"
; active= Config.annotation_reachability
; callbacks= [(Procedure AnnotationReachability.checker, Language.Java)] }
; { name= "nullable checks"
; active= Config.check_nullable
; callbacks=
[ (Procedure NullabilityCheck.checker, Language.Clang)
; (Procedure NullabilityCheck.checker, Language.Java) ] }
; { name= "biabduction"
; active= Config.biabduction
; callbacks=
[ (Procedure Interproc.analyze_procedure, Language.Clang)
; (DynamicDispatch Interproc.analyze_procedure, Language.Java) ] }
; { name= "buffer overrun"
; active= Config.bufferoverrun
; callbacks=
[ (Procedure BufferOverrunChecker.checker, Language.Clang)
; (Procedure BufferOverrunChecker.checker, Language.Java) ] }
; { name= "crashcontext"
; active= Config.crashcontext
; callbacks= [(Procedure BoundedCallTree.checker, Language.Java)] }
; { name= "eradicate"
; active= Config.eradicate
; callbacks= [(Procedure Eradicate.callback_eradicate, Language.Java)] }
; { name= "fragment retains view"
; active= Config.fragment_retains_view
; callbacks=
[(Procedure FragmentRetainsViewChecker.callback_fragment_retains_view, Language.Java)] }
; { name= "immutable cast"
; active= Config.immutable_cast
; callbacks= [(Procedure ImmutableChecker.callback_check_immutable_cast, Language.Java)] }
; { name= "liveness"
; active= Config.liveness
; callbacks= [(Procedure Liveness.checker, Language.Clang)] }
; { name= "printf args"
; active= Config.printf_args
; callbacks= [(Procedure PrintfArgs.callback_printf_args, Language.Java)] }
; { name= "nullable suggestion"
; active= Config.suggest_nullable
; callbacks=
[ (Procedure NullabilitySuggest.checker, Language.Java)
; (Procedure NullabilitySuggest.checker, Language.Clang) ] }
; { name= "ownership"
; active= Config.ownership
; callbacks= [(Procedure Ownership.checker, Language.Clang)] }
; { name= "quandary"
; active= Config.quandary
; callbacks=
[ (Procedure JavaTaintAnalysis.checker, Language.Java)
; (Procedure ClangTaintAnalysis.checker, Language.Clang) ] }
; { name= "RacerD"
; active= Config.racerd
; callbacks=
[ (Procedure RacerD.analyze_procedure, Language.Clang)
; (Procedure RacerD.analyze_procedure, Language.Java)
; (Cluster RacerD.file_analysis, Language.Clang)
; (Cluster RacerD.file_analysis, Language.Java) ] }
(* toy resource analysis to use in the infer lab, see the lab/ directory *)
; { name= "resource leak"
; active= Config.resource_leak
; callbacks=
[ ( (* the checked-in version is intraprocedural, but the lab asks to make it
interprocedural later on *)
Procedure ResourceLeaks.checker
, Language.Java ) ] }
; {name= "litho"; active= Config.litho; callbacks= [(Procedure Litho.checker, Language.Java)]}
; {name= "SIOF"; active= Config.siof; callbacks= [(Procedure Siof.checker, Language.Clang)]}
; { name= "uninitialized variables"
; active= Config.uninit
; callbacks= [(Procedure Uninit.checker, Language.Clang)] }
; { name= "cost analysis"
; active= Config.cost
; callbacks= [(Procedure Cost.checker, Language.Clang); (Procedure Cost.checker, Language.Java)]
}
; { name= "Starvation analysis"
; active= Config.starvation
; callbacks=
[ (Procedure Starvation.analyze_procedure, Language.Java)
; (Cluster Starvation.reporting, Language.Java) ] } ]
let get_active_checkers () =
let filter_checker {active} = active in
List.filter ~f:filter_checker all_checkers
let register checkers =
let register_one {callbacks} =
let register_callback (callback, language) =
match callback with
| Procedure procedure_cb ->
Callbacks.register_procedure_callback language procedure_cb
| DynamicDispatch procedure_cb ->
Callbacks.register_procedure_callback ~dynamic_dispatch:true language procedure_cb
| Cluster cluster_cb ->
Callbacks.register_cluster_callback language cluster_cb
in
List.iter ~f:register_callback callbacks
in
List.iter ~f:register_one checkers
module LanguageSet = Caml.Set.Make (Language)
let pp_checker fmt {name; callbacks} =
let langs_of_callbacks =
List.fold_left callbacks ~init:LanguageSet.empty ~f:(fun langs (_, lang) ->
LanguageSet.add lang langs )
|> LanguageSet.elements
in
F.fprintf fmt "%s (%a)" name
(Pp.seq ~sep:", " (Pp.to_string ~f:Language.to_string))
langs_of_callbacks