(* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. *) open! IStd module L = Die type t = | AnnotationReachability | Biabduction | BufferOverrunAnalysis | BufferOverrunChecker | ClassLoads | Cost | Eradicate | FragmentRetainsView | ImmutableCast | Impurity | InefficientKeysetIterator | Linters | LithoRequiredProps | Liveness | LoopHoisting | NullsafeDeprecated | PrintfArgs | Pulse | Purity | Quandary | RacerD | ResourceLeakLabExercise | SIOF | SelfInBlock | Starvation | TOPL | Uninit [@@deriving equal, enumerate] type support = NoSupport | Support | ExperimentalSupport | ToySupport type cli_flags = {long: string; deprecated: string list; show_in_help: bool} type config = { id: string ; support: Language.t -> support ; short_documentation: string ; cli_flags: cli_flags option ; enabled_by_default: bool ; activates: t list } (* support for languages should be consistent with the corresponding callbacks registered. Or maybe with the issues reported in link with each analysis. Some runtime check probably needed. *) let config_unsafe checker = let supports_clang_and_java _ = Support in let supports_clang_and_java_experimental _ = ExperimentalSupport in let supports_clang (language : Language.t) = match language with Clang -> Support | Java -> NoSupport in let supports_java (language : Language.t) = match language with Clang -> NoSupport | Java -> Support in let supports_java_experimental (language : Language.t) = match language with Clang -> NoSupport | Java -> ExperimentalSupport in match checker with | AnnotationReachability -> { id= "annotation-reachability" ; support= supports_clang_and_java ; short_documentation= "the annotation reachability checker. Given a pair of source and sink annotation, e.g. \ @PerformanceCritical and @Expensive, this checker will warn whenever some method \ annotated with @PerformanceCritical calls, directly or indirectly, another method \ annotated with @Expensive" ; cli_flags= Some {long= "annotation-reachability"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [] } | Biabduction -> { id= "biabduction" ; support= supports_clang_and_java ; short_documentation= "the separation logic based bi-abduction analysis using the checkers framework" ; cli_flags= Some {long= "biabduction"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | BufferOverrunAnalysis -> { id= "buffer-overrun-analysis" ; support= supports_clang_and_java ; short_documentation= "internal part of the buffer overrun analysis that computes values at each program \ point, automatically triggered when analyses that depend on these are run" ; cli_flags= None ; enabled_by_default= false ; activates= [] } | BufferOverrunChecker -> { id= "buffer-overrun-checker" ; support= supports_clang_and_java ; short_documentation= "the buffer overrun analysis" ; cli_flags= Some {long= "bufferoverrun"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [BufferOverrunAnalysis] } | ClassLoads -> { id= "class-loading-analysis" ; support= supports_java ; short_documentation= "Java class loading analysis" ; cli_flags= Some {long= "class-loads"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [] } | Cost -> { id= "cost-analysis" ; support= supports_clang_and_java ; short_documentation= "checker for performance cost analysis" ; cli_flags= Some {long= "cost"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [BufferOverrunAnalysis] } | Eradicate -> { id= "eradicate" ; support= supports_java ; short_documentation= "the eradicate @Nullable checker for Java annotations" ; cli_flags= Some {long= "eradicate"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [] } | FragmentRetainsView -> { id= "fragment-retains-view" ; support= supports_java ; short_documentation= "detects when Android fragments are not explicitly nullified before becoming unreabable" ; cli_flags= Some {long= "fragment-retains-view"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | ImmutableCast -> { id= "immutable-cast" ; support= supports_java ; short_documentation= "the detection of object cast from immutable type to mutable type. For instance, it will \ detect cast from ImmutableList to List, ImmutableMap to Map, and ImmutableSet to Set." ; cli_flags= Some {long= "immutable-cast"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [] } | Impurity -> { id= "impurity" ; support= supports_clang_and_java_experimental ; short_documentation= "[EXPERIMENTAL] Impurity analysis" ; cli_flags= Some {long= "impurity"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [Pulse] } | InefficientKeysetIterator -> { id= "inefficient-keyset-iterator" ; support= supports_java ; short_documentation= "Check for inefficient uses of keySet iterator that access both the key and the value." ; cli_flags= Some {long= "inefficient-keyset-iterator"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | Linters -> { id= "al-linters" ; support= supports_clang ; short_documentation= "syntactic linters" ; cli_flags= Some {long= "linters"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | LithoRequiredProps -> { id= "litho-required-props" ; support= supports_java_experimental ; short_documentation= "[EXPERIMENTAL] Required Prop check for Litho" ; cli_flags= Some {long= "litho-required-props"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [] } | Liveness -> { id= "liveness" ; support= supports_clang ; short_documentation= "the detection of dead stores and unused variables" ; cli_flags= Some {long= "liveness"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | LoopHoisting -> { id= "loop-hoisting" ; support= supports_clang_and_java ; short_documentation= "checker for loop-hoisting" ; cli_flags= Some {long= "loop-hoisting"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [BufferOverrunAnalysis; Purity] } | NullsafeDeprecated -> { id= "nullsafe" ; support= (fun _ -> NoSupport) ; short_documentation= "[RESERVED] Reserved for nullsafe typechecker, use --eradicate for now" ; cli_flags= Some { long= "nullsafe" ; deprecated= ["-check-nullable"; "-suggest-nullable"] ; show_in_help= false } ; enabled_by_default= false ; activates= [] } | PrintfArgs -> { id= "printf-args" ; support= supports_java ; short_documentation= "the detection of mismatch between the Java printf format strings and the argument types \ For, example, this checker will warn about the type error in `printf(\"Hello %d\", \ \"world\")`" ; cli_flags= Some {long= "printf-args"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [] } | Pulse -> { id= "pulse" ; support= supports_clang_and_java_experimental ; short_documentation= "[EXPERIMENTAL] memory and lifetime analysis" ; cli_flags= Some {long= "pulse"; deprecated= ["-ownership"]; show_in_help= true} ; enabled_by_default= false ; activates= [] } | Purity -> { id= "purity" ; support= supports_clang_and_java_experimental ; short_documentation= "[EXPERIMENTAL] Purity analysis" ; cli_flags= Some {long= "purity"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [BufferOverrunAnalysis] } | Quandary -> { id= "quandary" ; support= supports_clang_and_java ; short_documentation= "the quandary taint analysis" ; cli_flags= Some {long= "quandary"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [] } | RacerD -> { id= "RacerD" ; support= supports_clang_and_java ; short_documentation= "the RacerD thread safety analysis" ; cli_flags= Some {long= "racerd"; deprecated= ["-threadsafety"]; show_in_help= true} ; enabled_by_default= true ; activates= [] } | ResourceLeakLabExercise -> { id= "resource-leak-lab" ; support= (fun _ -> ToySupport) ; short_documentation= "" ; cli_flags= Some {long= "resource-leak"; deprecated= []; show_in_help= false} ; enabled_by_default= false ; activates= [] } | SIOF -> { id= "SIOF" ; support= supports_clang ; short_documentation= "the Static Initialization Order Fiasco analysis (C++ only)" ; cli_flags= Some {long= "siof"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | SelfInBlock -> { id= "self-in-block" ; support= supports_clang ; short_documentation= "checker to flag incorrect uses of when Objective-C blocks capture self" ; cli_flags= Some {long= "self_in_block"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | Starvation -> { id= "starvation" ; support= supports_clang_and_java ; short_documentation= "starvation analysis" ; cli_flags= Some {long= "starvation"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } | TOPL -> { id= "TOPL" ; support= supports_clang_and_java_experimental ; short_documentation= "TOPL" ; cli_flags= Some {long= "topl"; deprecated= []; show_in_help= true} ; enabled_by_default= false ; activates= [Biabduction] } | Uninit -> { id= "uninit" ; support= supports_clang ; short_documentation= "checker for use of uninitialized values" ; cli_flags= Some {long= "uninit"; deprecated= []; show_in_help= true} ; enabled_by_default= true ; activates= [] } let config c = let config = config_unsafe c in let is_illegal_id_char c = match c with 'a' .. 'z' | 'A' .. 'Z' | '-' -> false | _ -> true in String.find config.id ~f:is_illegal_id_char |> Option.iter ~f:(fun c -> L.die InternalError "Illegal character '%c' in id: '%s'. Checker ids must be easy to pass on the command \ line." c config.id ) ; config let get_id c = (config c).id let from_id id = List.find all ~f:(fun checker -> String.equal (get_id checker) id)