diff --git a/infer/src/IR/Exceptions.ml b/infer/src/IR/Exceptions.ml index e36caea7c..c4a29463d 100644 --- a/infer/src/IR/Exceptions.ml +++ b/infer/src/IR/Exceptions.ml @@ -241,7 +241,7 @@ let recognize_exception exn = ; severity= None ; category= Nocat } | Custom_error (error_msg, desc) -> - { name= IssueType.register_from_string error_msg + { name= IssueType.register_from_string ~id:error_msg [Biabduction] ; description= desc ; ocaml_pos= None ; visibility= Exn_user @@ -362,7 +362,7 @@ let recognize_exception exn = ; category= Nocat } | Java_runtime_exception (exn_name, _, desc) -> let exn_str = Typ.Name.name exn_name in - { name= IssueType.register_from_string exn_str + { name= IssueType.register_from_string ~id:exn_str [Biabduction] ; description= desc ; ocaml_pos= None ; visibility= Exn_user diff --git a/infer/src/al/ALIssues.ml b/infer/src/al/ALIssues.ml index 1ea81dee6..d3787a2c1 100644 --- a/infer/src/al/ALIssues.ml +++ b/infer/src/al/ALIssues.ml @@ -262,8 +262,8 @@ let create_parsed_linters linters_def_file checkers : linter list = (Config.get_linter_doc_url ~linter_id:checker.id) issue_desc.issue_type.doc_url in - IssueType.register_from_string checker.id ?hum:issue_desc.issue_type.name ?doc_url - ~linters_def_file + IssueType.register_from_string ~id:checker.id ?hum:issue_desc.issue_type.name ?doc_url + ~linters_def_file [Linters] in let issue_desc = {issue_desc with issue_type} in L.(debug Linters Medium) "@\nIssue_desc = %a@\n" CIssue.pp_issue issue_desc ; diff --git a/infer/src/backend/registerCheckers.ml b/infer/src/backend/registerCheckers.ml index 698761043..4421258eb 100644 --- a/infer/src/backend/registerCheckers.ml +++ b/infer/src/backend/registerCheckers.ml @@ -138,7 +138,7 @@ let all_checkers = } ; (* toy resource analysis to use in the infer lab, see the lab/ directory *) { name= "resource leak" - ; active= Config.is_checker_enabled ResourceLeak + ; active= Config.is_checker_enabled ResourceLeakLabExercise ; callbacks= [ ( (* the checked-in version is intraprocedural, but the lab asks to make it interprocedural later on *) diff --git a/infer/src/base/Checker.ml b/infer/src/base/Checker.ml index 3cd23f8e6..13bf51ba3 100644 --- a/infer/src/base/Checker.ml +++ b/infer/src/base/Checker.ml @@ -28,7 +28,7 @@ type t = | Purity | Quandary | RacerD - | ResourceLeak + | ResourceLeakLabExercise | SIOF | SelfInBlock | Starvation @@ -214,7 +214,7 @@ let config checker = ; cli_flag= "racerd" ; enabled_by_default= true ; cli_deprecated_flags= ["-threadsafety"] } - | ResourceLeak -> + | ResourceLeakLabExercise -> { support= (fun _ -> ToySupport) ; short_documentation= "" ; show_in_help= false diff --git a/infer/src/base/Checker.mli b/infer/src/base/Checker.mli index 9e5f4ce3f..65ad658b3 100644 --- a/infer/src/base/Checker.mli +++ b/infer/src/base/Checker.mli @@ -28,7 +28,7 @@ type t = | Purity | Quandary | RacerD - | ResourceLeak + | ResourceLeakLabExercise | SIOF | SelfInBlock | Starvation diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 03b4fe8b3..38612ec71 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -1169,7 +1169,7 @@ and () = let (_ : string list ref) = CLOpt.mk_string_list ?deprecated ~long ~f:(fun issue_id -> - let issue = IssueType.register_from_string issue_id in + let issue = IssueType.register_from_string ~id:issue_id [Linters] in IssueType.set_enabled issue b ; issue_id ) ?default ~meta:"issue_type" diff --git a/infer/src/base/IssueType.ml b/infer/src/base/IssueType.ml index b39ea481d..d1b40f13a 100644 --- a/infer/src/base/IssueType.ml +++ b/infer/src/base/IssueType.ml @@ -11,6 +11,7 @@ open! IStd module Unsafe : sig type t = private { unique_id: string + ; checkers: Checker.t list ; mutable enabled: bool ; mutable hum: string ; mutable doc_url: string option @@ -20,7 +21,13 @@ module Unsafe : sig val equal : t -> t -> bool val register_from_string : - ?enabled:bool -> ?hum:string -> ?doc_url:string -> ?linters_def_file:string -> string -> t + ?enabled:bool + -> ?hum:string + -> ?doc_url:string + -> ?linters_def_file:string + -> id:string + -> Checker.t list + -> t val register_from_cost_string : ?enabled:bool @@ -36,6 +43,7 @@ end = struct module T = struct type t = { unique_id: string + ; checkers: Checker.t list ; mutable enabled: bool ; mutable hum: string ; mutable doc_url: string option @@ -70,9 +78,10 @@ end = struct but issues of type 2. have not yet been defined. Thus, we record only there [enabled] status definitely. The [hum]an-readable description can be updated when we encounter the definition of the issue type, eg in AL. *) - let register_from_string ?(enabled = true) ?hum:hum0 ?doc_url ?linters_def_file unique_id = + let register_from_string ?(enabled = true) ?hum:hum0 ?doc_url ?linters_def_file ~id:unique_id + checkers = let hum = match hum0 with Some str -> str | _ -> prettify unique_id in - let issue = {unique_id; enabled; hum; doc_url; linters_def_file} in + let issue = {unique_id; checkers; enabled; hum; doc_url; linters_def_file} in try let old = IssueSet.find issue !all_issues in (* update human-readable string in case it was supplied this time, but keep the previous @@ -91,7 +100,7 @@ end = struct = let issue_type_base = Format.asprintf s (CostKind.to_issue_string kind) in let issue_type = if is_on_ui_thread then issue_type_base ^ "_UI_THREAD" else issue_type_base in - register_from_string ~enabled issue_type + register_from_string ~enabled ~id:issue_type [Cost] let all_issues () = IssueSet.elements !all_issues @@ -102,204 +111,232 @@ include Unsafe (** pretty print a localised string *) let pp fmt t = Format.pp_print_string fmt t.unique_id -let abduction_case_not_implemented = register_from_string "Abduction_case_not_implemented" +let checker_can_report checker {checkers} = List.mem ~equal:Checker.equal checkers checker + +let abduction_case_not_implemented = + register_from_string ~id:"Abduction_case_not_implemented" [Biabduction] + + +let analysis_stops = register_from_string ~enabled:false ~id:"ANALYSIS_STOPS" [Biabduction] -let analysis_stops = register_from_string ~enabled:false "ANALYSIS_STOPS" +let array_of_pointsto = register_from_string ~id:"Array_of_pointsto" [Biabduction] -let array_of_pointsto = register_from_string "Array_of_pointsto" +let array_out_of_bounds_l1 = + register_from_string ~enabled:false ~id:"ARRAY_OUT_OF_BOUNDS_L1" [Biabduction] -let array_out_of_bounds_l1 = register_from_string ~enabled:false "ARRAY_OUT_OF_BOUNDS_L1" -let array_out_of_bounds_l2 = register_from_string ~enabled:false "ARRAY_OUT_OF_BOUNDS_L2" +let array_out_of_bounds_l2 = + register_from_string ~enabled:false ~id:"ARRAY_OUT_OF_BOUNDS_L2" [Biabduction] -let array_out_of_bounds_l3 = register_from_string ~enabled:false "ARRAY_OUT_OF_BOUNDS_L3" -let assert_failure = register_from_string "Assert_failure" +let array_out_of_bounds_l3 = + register_from_string ~enabled:false ~id:"ARRAY_OUT_OF_BOUNDS_L3" [Biabduction] -let bad_footprint = register_from_string "Bad_footprint" -let buffer_overrun_l1 = register_from_string "BUFFER_OVERRUN_L1" +let assert_failure = register_from_string ~id:"Assert_failure" [Biabduction] -let buffer_overrun_l2 = register_from_string "BUFFER_OVERRUN_L2" +let bad_footprint = register_from_string ~id:"Bad_footprint" [Biabduction] -let buffer_overrun_l3 = register_from_string "BUFFER_OVERRUN_L3" +let buffer_overrun_l1 = register_from_string ~id:"BUFFER_OVERRUN_L1" [BufferOverrun] -let buffer_overrun_l4 = register_from_string ~enabled:false "BUFFER_OVERRUN_L4" +let buffer_overrun_l2 = register_from_string ~id:"BUFFER_OVERRUN_L2" [BufferOverrun] -let buffer_overrun_l5 = register_from_string ~enabled:false "BUFFER_OVERRUN_L5" +let buffer_overrun_l3 = register_from_string ~id:"BUFFER_OVERRUN_L3" [BufferOverrun] -let buffer_overrun_r2 = register_from_string "BUFFER_OVERRUN_R2" +let buffer_overrun_l4 = register_from_string ~enabled:false ~id:"BUFFER_OVERRUN_L4" [BufferOverrun] -let buffer_overrun_s2 = register_from_string "BUFFER_OVERRUN_S2" +let buffer_overrun_l5 = register_from_string ~enabled:false ~id:"BUFFER_OVERRUN_L5" [BufferOverrun] -let buffer_overrun_t1 = register_from_string "BUFFER_OVERRUN_T1" +let buffer_overrun_r2 = register_from_string ~id:"BUFFER_OVERRUN_R2" [BufferOverrun] -let buffer_overrun_u5 = register_from_string ~enabled:false "BUFFER_OVERRUN_U5" +let buffer_overrun_s2 = register_from_string ~id:"BUFFER_OVERRUN_S2" [BufferOverrun] -let cannot_star = register_from_string "Cannot_star" +let buffer_overrun_t1 = register_from_string ~id:"BUFFER_OVERRUN_T1" [BufferOverrun] + +let buffer_overrun_u5 = register_from_string ~enabled:false ~id:"BUFFER_OVERRUN_U5" [BufferOverrun] + +let cannot_star = register_from_string ~id:"Cannot_star" [Biabduction] + +let captured_strong_self = + register_from_string ~id:"CAPTURED_STRONG_SELF" ~hum:"Captured strongSelf" [SelfInBlock] -let captured_strong_self = register_from_string "CAPTURED_STRONG_SELF" ~hum:"Captured strongSelf" let checkers_allocates_memory = - register_from_string "CHECKERS_ALLOCATES_MEMORY" ~hum:"Allocates Memory" + register_from_string ~id:"CHECKERS_ALLOCATES_MEMORY" ~hum:"Allocates Memory" + [AnnotationReachability] let checkers_annotation_reachability_error = - register_from_string "CHECKERS_ANNOTATION_REACHABILITY_ERROR" ~hum:"Annotation Reachability Error" + register_from_string ~id:"CHECKERS_ANNOTATION_REACHABILITY_ERROR" + ~hum:"Annotation Reachability Error" [AnnotationReachability] let checkers_calls_expensive_method = - register_from_string "CHECKERS_CALLS_EXPENSIVE_METHOD" ~hum:"Expensive Method Called" + register_from_string ~id:"CHECKERS_CALLS_EXPENSIVE_METHOD" ~hum:"Expensive Method Called" + [AnnotationReachability] let checkers_expensive_overrides_unexpensive = - register_from_string "CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED" - ~hum:"Expensive Overrides Unannotated" + register_from_string ~id:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED" + ~hum:"Expensive Overrides Unannotated" [AnnotationReachability] let checkers_fragment_retain_view = - register_from_string "CHECKERS_FRAGMENT_RETAINS_VIEW" ~hum:"Fragment Retains View" + register_from_string ~id:"CHECKERS_FRAGMENT_RETAINS_VIEW" ~hum:"Fragment Retains View" + [FragmentRetainsView] + +let checkers_immutable_cast = register_from_string ~id:"CHECKERS_IMMUTABLE_CAST" [ImmutableCast] -let checkers_immutable_cast = register_from_string "CHECKERS_IMMUTABLE_CAST" +let checkers_printf_args = register_from_string ~id:"CHECKERS_PRINTF_ARGS" [PrintfArgs] -let checkers_printf_args = register_from_string "CHECKERS_PRINTF_ARGS" +let class_cast_exception = + register_from_string ~enabled:false ~id:"CLASS_CAST_EXCEPTION" [Biabduction] -let class_cast_exception = register_from_string ~enabled:false "CLASS_CAST_EXCEPTION" -let class_load = register_from_string "CLASS_LOAD" +let class_load = register_from_string ~id:"CLASS_LOAD" [ClassLoads] -let codequery = register_from_string "Codequery" +let codequery = register_from_string ~id:"Codequery" [Biabduction] -let comparing_floats_for_equality = register_from_string "COMPARING_FLOAT_FOR_EQUALITY" +let comparing_floats_for_equality = + register_from_string ~id:"COMPARING_FLOAT_FOR_EQUALITY" [Biabduction] -let component_factory_function = register_from_string "COMPONENT_FACTORY_FUNCTION" + +let component_factory_function = register_from_string ~id:"COMPONENT_FACTORY_FUNCTION" [Linters] let component_file_cyclomatic_complexity = - register_from_string "COMPONENT_FILE_CYCLOMATIC_COMPLEXITY" + register_from_string ~id:"COMPONENT_FILE_CYCLOMATIC_COMPLEXITY" [Linters] + +let component_file_line_count = + register_from_string ~enabled:false ~id:"COMPONENT_FILE_LINE_COUNT" [Linters] -let component_file_line_count = register_from_string ~enabled:false "COMPONENT_FILE_LINE_COUNT" let component_initializer_with_side_effects = - register_from_string "COMPONENT_INITIALIZER_WITH_SIDE_EFFECTS" + register_from_string ~id:"COMPONENT_INITIALIZER_WITH_SIDE_EFFECTS" [Linters] let component_with_multiple_factory_methods = - register_from_string "COMPONENT_WITH_MULTIPLE_FACTORY_METHODS" + register_from_string ~id:"COMPONENT_WITH_MULTIPLE_FACTORY_METHODS" [Linters] let component_with_unconventional_superclass = - register_from_string "COMPONENT_WITH_UNCONVENTIONAL_SUPERCLASS" + register_from_string ~id:"COMPONENT_WITH_UNCONVENTIONAL_SUPERCLASS" [Linters] + +let condition_always_false = + register_from_string ~enabled:false ~id:"CONDITION_ALWAYS_FALSE" [Biabduction; BufferOverrun] -let condition_always_false = register_from_string ~enabled:false "CONDITION_ALWAYS_FALSE" -let condition_always_true = register_from_string ~enabled:false "CONDITION_ALWAYS_TRUE" +let condition_always_true = + register_from_string ~enabled:false ~id:"CONDITION_ALWAYS_TRUE" [Biabduction; BufferOverrun] + let constant_address_dereference = - register_from_string ~enabled:false "CONSTANT_ADDRESS_DEREFERENCE" + register_from_string ~enabled:false ~id:"CONSTANT_ADDRESS_DEREFERENCE" [Pulse] -let create_intent_from_uri = register_from_string "CREATE_INTENT_FROM_URI" +let create_intent_from_uri = register_from_string ~id:"CREATE_INTENT_FROM_URI" [Quandary] -let cross_site_scripting = register_from_string "CROSS_SITE_SCRIPTING" +let cross_site_scripting = register_from_string ~id:"CROSS_SITE_SCRIPTING" [Quandary] let dangling_pointer_dereference = - register_from_string ~enabled:false "DANGLING_POINTER_DEREFERENCE" + register_from_string ~enabled:false ~id:"DANGLING_POINTER_DEREFERENCE" [Biabduction] -let dead_store = register_from_string "DEAD_STORE" +let dead_store = register_from_string ~id:"DEAD_STORE" [Liveness] -let deadlock = register_from_string "DEADLOCK" +let deadlock = register_from_string ~id:"DEADLOCK" [Starvation] -let deallocate_stack_variable = register_from_string "DEALLOCATE_STACK_VARIABLE" +let deallocate_stack_variable = register_from_string ~id:"DEALLOCATE_STACK_VARIABLE" [Biabduction] -let deallocate_static_memory = register_from_string "DEALLOCATE_STATIC_MEMORY" +let deallocate_static_memory = register_from_string ~id:"DEALLOCATE_STATIC_MEMORY" [Biabduction] -let deallocation_mismatch = register_from_string "DEALLOCATION_MISMATCH" +let deallocation_mismatch = register_from_string ~id:"DEALLOCATION_MISMATCH" [Biabduction] -let divide_by_zero = register_from_string ~enabled:false "DIVIDE_BY_ZERO" +let divide_by_zero = register_from_string ~enabled:false ~id:"DIVIDE_BY_ZERO" [Biabduction] -let do_not_report = register_from_string "DO_NOT_REPORT" +let do_not_report = register_from_string ~id:"DO_NOT_REPORT" [Quandary] -let empty_vector_access = register_from_string "EMPTY_VECTOR_ACCESS" +let empty_vector_access = register_from_string ~id:"EMPTY_VECTOR_ACCESS" [Biabduction] let eradicate_condition_redundant = - register_from_string "ERADICATE_CONDITION_REDUNDANT" ~hum:"Condition Redundant" + register_from_string ~id:"ERADICATE_CONDITION_REDUNDANT" ~hum:"Condition Redundant" [Eradicate] (* TODO(T54070503) remove condition redundant nonnull *) let _ = - register_from_string "ERADICATE_CONDITION_REDUNDANT_NONNULL" ~hum:"Condition Redundant Non-Null" + register_from_string ~id:"ERADICATE_CONDITION_REDUNDANT_NONNULL" + ~hum:"Condition Redundant Non-Null" [Eradicate] let eradicate_field_not_initialized = - register_from_string "ERADICATE_FIELD_NOT_INITIALIZED" ~hum:"Field Not Initialized" + register_from_string ~id:"ERADICATE_FIELD_NOT_INITIALIZED" ~hum:"Field Not Initialized" [Eradicate] let eradicate_field_not_nullable = - register_from_string "ERADICATE_FIELD_NOT_NULLABLE" ~hum:"Field Not Nullable" + register_from_string ~id:"ERADICATE_FIELD_NOT_NULLABLE" ~hum:"Field Not Nullable" [Eradicate] let eradicate_field_over_annotated = - register_from_string "ERADICATE_FIELD_OVER_ANNOTATED" ~hum:"Field Over Annotated" + register_from_string ~id:"ERADICATE_FIELD_OVER_ANNOTATED" ~hum:"Field Over Annotated" [Eradicate] let eradicate_inconsistent_subclass_parameter_annotation = - register_from_string "ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION" - ~hum:"Inconsistent Subclass Parameter Annotation" + register_from_string ~id:"ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION" + ~hum:"Inconsistent Subclass Parameter Annotation" [Eradicate] let eradicate_inconsistent_subclass_return_annotation = - register_from_string "ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION" - ~hum:"Inconsistent Subclass Return Annotation" + register_from_string ~id:"ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION" + ~hum:"Inconsistent Subclass Return Annotation" [Eradicate] let eradicate_redundant_nested_class_annotation = - register_from_string "ERADICATE_REDUNDANT_NESTED_CLASS_ANNOTATION" - ~hum:"@Nullsafe annotation is redundant" + register_from_string ~id:"ERADICATE_REDUNDANT_NESTED_CLASS_ANNOTATION" + ~hum:"@Nullsafe annotation is redundant" [Eradicate] let eradicate_bad_nested_class_annotation = - register_from_string "ERADICATE_BAD_NESTED_CLASS_ANNOTATION" - ~hum:"@Nullsafe annotation is inconsistent with outer class" + register_from_string ~id:"ERADICATE_BAD_NESTED_CLASS_ANNOTATION" + ~hum:"@Nullsafe annotation is inconsistent with outer class" [Eradicate] let eradicate_nullable_dereference = - register_from_string "ERADICATE_NULLABLE_DEREFERENCE" ~hum:"Nullable Dereference" + register_from_string ~id:"ERADICATE_NULLABLE_DEREFERENCE" ~hum:"Nullable Dereference" [Eradicate] let eradicate_parameter_not_nullable = - register_from_string "ERADICATE_PARAMETER_NOT_NULLABLE" ~hum:"Parameter Not Nullable" + register_from_string ~id:"ERADICATE_PARAMETER_NOT_NULLABLE" ~hum:"Parameter Not Nullable" + [Eradicate] let eradicate_return_not_nullable = - register_from_string "ERADICATE_RETURN_NOT_NULLABLE" ~hum:"Return Not Nullable" + register_from_string ~id:"ERADICATE_RETURN_NOT_NULLABLE" ~hum:"Return Not Nullable" [Eradicate] let eradicate_return_over_annotated = - register_from_string "ERADICATE_RETURN_OVER_ANNOTATED" ~hum:"Return Over Annotated" + register_from_string ~id:"ERADICATE_RETURN_OVER_ANNOTATED" ~hum:"Return Over Annotated" [Eradicate] let eradicate_unchecked_usage_in_nullsafe = - register_from_string "ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE" - ~hum:"Nullsafe mode: unchecked usage of a value" + register_from_string ~id:"ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE" + ~hum:"Nullsafe mode: unchecked usage of a value" [Eradicate] let eradicate_unvetted_third_party_in_nullsafe = - register_from_string "ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE" - ~hum:"Nullsafe mode: unchecked usage of unvetted third-party" + register_from_string ~id:"ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE" + ~hum:"Nullsafe mode: unchecked usage of unvetted third-party" [Eradicate] (* Meta issues in eradicate are technical issues reflecting null-safety state of classes in general, in contrast with concrete nullability type violations *) let eradicate_meta_class_is_nullsafe = - register_from_string "ERADICATE_META_CLASS_IS_NULLSAFE" + register_from_string ~id:"ERADICATE_META_CLASS_IS_NULLSAFE" ~hum: "Class is marked @Nullsafe and has 0 issues" (* Should be enabled for special integrations *) - ~enabled:false + ~enabled:false [Eradicate] (* Class is either: @@ -307,226 +344,272 @@ let eradicate_meta_class_is_nullsafe = - has at least one (currently possibly hidden) issue in order to be marked as @Nullsafe. *) let eradicate_meta_class_needs_improvement = - register_from_string "ERADICATE_META_CLASS_NEEDS_IMPROVEMENT" + register_from_string ~id:"ERADICATE_META_CLASS_NEEDS_IMPROVEMENT" ~hum: "Class needs improvement to become @Nullsafe" (* Should be enabled for special integrations *) - ~enabled:false + ~enabled:false [Eradicate] let eradicate_meta_class_can_be_nullsafe = - register_from_string "ERADICATE_META_CLASS_CAN_BE_NULLSAFE" + register_from_string ~id:"ERADICATE_META_CLASS_CAN_BE_NULLSAFE" ~hum: "Class has 0 issues and can be marked @Nullsafe" - (* Should be enabled for special integrations *) ~enabled:false + (* Should be enabled for special integrations *) ~enabled:false [Eradicate] let expensive_cost_call ~kind ~is_on_ui_thread = register_from_cost_string ~enabled:false ~kind ~is_on_ui_thread "EXPENSIVE_%s" -let exposed_insecure_intent_handling = register_from_string "EXPOSED_INSECURE_INTENT_HANDLING" +let exposed_insecure_intent_handling = + register_from_string ~id:"EXPOSED_INSECURE_INTENT_HANDLING" [Quandary] + -let failure_exe = register_from_string "Failure_exe" +let failure_exe = register_from_string ~id:"Failure_exe" [Biabduction] -let field_not_null_checked = register_from_string "IVAR_NOT_NULL_CHECKED" +let field_not_null_checked = register_from_string ~id:"IVAR_NOT_NULL_CHECKED" [Biabduction] (* from AL default linters *) let _global_variable_initialized_with_function_or_method_call = - register_from_string ~enabled:false "GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL" + register_from_string ~enabled:false ~id:"GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL" + [Linters] let guardedby_violation_racerd = - register_from_string "GUARDEDBY_VIOLATION" ~hum:"GuardedBy Violation" + register_from_string ~id:"GUARDEDBY_VIOLATION" ~hum:"GuardedBy Violation" [RacerD] -let impure_function = register_from_string "IMPURE_FUNCTION" +let impure_function = register_from_string ~id:"IMPURE_FUNCTION" [Impurity] -let inefficient_keyset_iterator = register_from_string "INEFFICIENT_KEYSET_ITERATOR" +let inefficient_keyset_iterator = + register_from_string ~id:"INEFFICIENT_KEYSET_ITERATOR" [InefficientKeysetIterator] -let inferbo_alloc_is_big = register_from_string "INFERBO_ALLOC_IS_BIG" -let inferbo_alloc_is_negative = register_from_string "INFERBO_ALLOC_IS_NEGATIVE" +let inferbo_alloc_is_big = register_from_string ~id:"INFERBO_ALLOC_IS_BIG" [BufferOverrun] -let inferbo_alloc_is_zero = register_from_string "INFERBO_ALLOC_IS_ZERO" +let inferbo_alloc_is_negative = register_from_string ~id:"INFERBO_ALLOC_IS_NEGATIVE" [BufferOverrun] -let inferbo_alloc_may_be_big = register_from_string "INFERBO_ALLOC_MAY_BE_BIG" +let inferbo_alloc_is_zero = register_from_string ~id:"INFERBO_ALLOC_IS_ZERO" [BufferOverrun] -let inferbo_alloc_may_be_negative = register_from_string "INFERBO_ALLOC_MAY_BE_NEGATIVE" +let inferbo_alloc_may_be_big = register_from_string ~id:"INFERBO_ALLOC_MAY_BE_BIG" [BufferOverrun] + +let inferbo_alloc_may_be_negative = + register_from_string ~id:"INFERBO_ALLOC_MAY_BE_NEGATIVE" [BufferOverrun] + + +let inferbo_alloc_may_be_tainted = + register_from_string ~id:"INFERBO_ALLOC_MAY_BE_TAINTED" [BufferOverrun] -let inferbo_alloc_may_be_tainted = register_from_string "INFERBO_ALLOC_MAY_BE_TAINTED" let infinite_cost_call ~kind = register_from_cost_string ~enabled:false "INFINITE_%s" ~kind -let inherently_dangerous_function = register_from_string "INHERENTLY_DANGEROUS_FUNCTION" +let inherently_dangerous_function = + register_from_string ~id:"INHERENTLY_DANGEROUS_FUNCTION" [Biabduction] + -let insecure_intent_handling = register_from_string "INSECURE_INTENT_HANDLING" +let insecure_intent_handling = register_from_string ~id:"INSECURE_INTENT_HANDLING" [Quandary] -let integer_overflow_l1 = register_from_string "INTEGER_OVERFLOW_L1" +let integer_overflow_l1 = register_from_string ~id:"INTEGER_OVERFLOW_L1" [BufferOverrun] -let integer_overflow_l2 = register_from_string "INTEGER_OVERFLOW_L2" +let integer_overflow_l2 = register_from_string ~id:"INTEGER_OVERFLOW_L2" [BufferOverrun] -let integer_overflow_l5 = register_from_string ~enabled:false "INTEGER_OVERFLOW_L5" +let integer_overflow_l5 = + register_from_string ~enabled:false ~id:"INTEGER_OVERFLOW_L5" [BufferOverrun] -let integer_overflow_r2 = register_from_string "INTEGER_OVERFLOW_R2" -let integer_overflow_u5 = register_from_string ~enabled:false "INTEGER_OVERFLOW_U5" +let integer_overflow_r2 = register_from_string ~id:"INTEGER_OVERFLOW_R2" [BufferOverrun] -let interface_not_thread_safe = register_from_string "INTERFACE_NOT_THREAD_SAFE" +let integer_overflow_u5 = + register_from_string ~enabled:false ~id:"INTEGER_OVERFLOW_U5" [BufferOverrun] -let internal_error = register_from_string "Internal_error" -let invariant_call = register_from_string ~enabled:false "INVARIANT_CALL" +let interface_not_thread_safe = register_from_string ~id:"INTERFACE_NOT_THREAD_SAFE" [RacerD] -let javascript_injection = register_from_string "JAVASCRIPT_INJECTION" +let internal_error = register_from_string ~id:"Internal_error" [Biabduction] -let leak_after_array_abstraction = register_from_string "Leak_after_array_abstraction" +let invariant_call = register_from_string ~enabled:false ~id:"INVARIANT_CALL" [LoopHoisting] -let leak_in_footprint = register_from_string "Leak_in_footprint" +let javascript_injection = register_from_string ~id:"JAVASCRIPT_INJECTION" [Quandary] -let lock_consistency_violation = register_from_string "LOCK_CONSISTENCY_VIOLATION" +let leak_after_array_abstraction = + register_from_string ~id:"Leak_after_array_abstraction" [Biabduction] -let lockless_violation = register_from_string "LOCKLESS_VIOLATION" -let logging_private_data = register_from_string "LOGGING_PRIVATE_DATA" +let leak_in_footprint = register_from_string ~id:"Leak_in_footprint" [Biabduction] -let expensive_loop_invariant_call = register_from_string "EXPENSIVE_LOOP_INVARIANT_CALL" +let lock_consistency_violation = register_from_string ~id:"LOCK_CONSISTENCY_VIOLATION" [RacerD] -let memory_leak = register_from_string "MEMORY_LEAK" +let lockless_violation = register_from_string ~id:"LOCKLESS_VIOLATION" [Starvation] -let missing_fld = register_from_string "Missing_fld" ~hum:"Missing Field" +let logging_private_data = register_from_string ~id:"LOGGING_PRIVATE_DATA" [Quandary] -let missing_required_prop = register_from_string "MISSING_REQUIRED_PROP" +let expensive_loop_invariant_call = + register_from_string ~id:"EXPENSIVE_LOOP_INVARIANT_CALL" [LoopHoisting] -let mixed_self_weakself = register_from_string "MIXED_SELF_WEAKSELF" ~hum:"Mixed Self WeakSelf" -let multiple_weakself = register_from_string "MULTIPLE_WEAKSELF" ~hum:"Multiple WeakSelf Use" +let memory_leak = register_from_string ~id:"MEMORY_LEAK" [Biabduction] + +let missing_fld = register_from_string ~id:"Missing_fld" ~hum:"Missing Field" [Biabduction] + +let missing_required_prop = register_from_string ~id:"MISSING_REQUIRED_PROP" [LithoRequiredProps] + +let mixed_self_weakself = + register_from_string ~id:"MIXED_SELF_WEAKSELF" ~hum:"Mixed Self WeakSelf" [SelfInBlock] + + +let multiple_weakself = + register_from_string ~id:"MULTIPLE_WEAKSELF" ~hum:"Multiple WeakSelf Use" [SelfInBlock] + let mutable_local_variable_in_component_file = - register_from_string "MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE" + register_from_string ~id:"MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE" [Linters] + +let null_dereference = register_from_string ~id:"NULL_DEREFERENCE" [Biabduction] -let null_dereference = register_from_string "NULL_DEREFERENCE" +let null_test_after_dereference = + register_from_string ~enabled:false ~id:"NULL_TEST_AFTER_DEREFERENCE" [Biabduction] -let null_test_after_dereference = register_from_string ~enabled:false "NULL_TEST_AFTER_DEREFERENCE" -let nullptr_dereference = register_from_string ~enabled:false "NULLPTR_DEREFERENCE" +let nullptr_dereference = register_from_string ~enabled:false ~id:"NULLPTR_DEREFERENCE" [Pulse] -let parameter_not_null_checked = register_from_string "PARAMETER_NOT_NULL_CHECKED" +let parameter_not_null_checked = register_from_string ~id:"PARAMETER_NOT_NULL_CHECKED" [Biabduction] -let pointer_size_mismatch = register_from_string "POINTER_SIZE_MISMATCH" +let pointer_size_mismatch = register_from_string ~id:"POINTER_SIZE_MISMATCH" [Biabduction] -let precondition_not_found = register_from_string "PRECONDITION_NOT_FOUND" +let precondition_not_found = register_from_string ~id:"PRECONDITION_NOT_FOUND" [Biabduction] -let precondition_not_met = register_from_string "PRECONDITION_NOT_MET" +let precondition_not_met = register_from_string ~id:"PRECONDITION_NOT_MET" [Biabduction] -let premature_nil_termination = register_from_string "PREMATURE_NIL_TERMINATION_ARGUMENT" +let premature_nil_termination = + register_from_string ~id:"PREMATURE_NIL_TERMINATION_ARGUMENT" [Biabduction] -let pulse_memory_leak = register_from_string ~enabled:false "PULSE_MEMORY_LEAK" -let pure_function = register_from_string "PURE_FUNCTION" +let pulse_memory_leak = register_from_string ~enabled:false ~id:"PULSE_MEMORY_LEAK" [Pulse] -let quandary_taint_error = register_from_string "QUANDARY_TAINT_ERROR" +let pure_function = register_from_string ~id:"PURE_FUNCTION" [Purity] + +let quandary_taint_error = register_from_string ~id:"QUANDARY_TAINT_ERROR" [Quandary] let registered_observer_being_deallocated = - register_from_string "REGISTERED_OBSERVER_BEING_DEALLOCATED" + register_from_string ~id:"REGISTERED_OBSERVER_BEING_DEALLOCATED" [Biabduction] + +let resource_leak = register_from_string ~id:"RESOURCE_LEAK" [Biabduction; ResourceLeakLabExercise] -let resource_leak = register_from_string "RESOURCE_LEAK" +let retain_cycle = register_from_string ~enabled:true ~id:"RETAIN_CYCLE" [Biabduction] -let retain_cycle = register_from_string ~enabled:true "RETAIN_CYCLE" +let return_expression_required = register_from_string ~id:"RETURN_EXPRESSION_REQUIRED" [Biabduction] -let return_expression_required = register_from_string "RETURN_EXPRESSION_REQUIRED" +let return_statement_missing = register_from_string ~id:"RETURN_STATEMENT_MISSING" [Biabduction] -let return_statement_missing = register_from_string "RETURN_STATEMENT_MISSING" +let return_value_ignored = + register_from_string ~enabled:false ~id:"RETURN_VALUE_IGNORED" [Biabduction] -let return_value_ignored = register_from_string ~enabled:false "RETURN_VALUE_IGNORED" -let skip_function = register_from_string ~enabled:false "SKIP_FUNCTION" +let skip_function = register_from_string ~enabled:false ~id:"SKIP_FUNCTION" [Biabduction] -let skip_pointer_dereference = register_from_string ~enabled:false "SKIP_POINTER_DEREFERENCE" +let skip_pointer_dereference = + register_from_string ~enabled:false ~id:"SKIP_POINTER_DEREFERENCE" [Biabduction] -let shell_injection = register_from_string "SHELL_INJECTION" -let shell_injection_risk = register_from_string "SHELL_INJECTION_RISK" +let shell_injection = register_from_string ~id:"SHELL_INJECTION" [Quandary] -let sql_injection = register_from_string "SQL_INJECTION" +let shell_injection_risk = register_from_string ~id:"SHELL_INJECTION_RISK" [Quandary] -let sql_injection_risk = register_from_string "SQL_INJECTION_RISK" +let sql_injection = register_from_string ~id:"SQL_INJECTION" [Quandary] + +let sql_injection_risk = register_from_string ~id:"SQL_INJECTION_RISK" [Quandary] let stack_variable_address_escape = - register_from_string ~enabled:false "STACK_VARIABLE_ADDRESS_ESCAPE" + register_from_string ~enabled:false ~id:"STACK_VARIABLE_ADDRESS_ESCAPE" [Biabduction; Pulse] + +let starvation = register_from_string ~id:"STARVATION" ~hum:"UI Thread Starvation" [Starvation] -let starvation = register_from_string "STARVATION" ~hum:"UI Thread Starvation" +let static_initialization_order_fiasco = + register_from_string ~id:"STATIC_INITIALIZATION_ORDER_FIASCO" [SIOF] -let static_initialization_order_fiasco = register_from_string "STATIC_INITIALIZATION_ORDER_FIASCO" let strict_mode_violation = - register_from_string "STRICT_MODE_VIOLATION" ~hum:"Strict Mode Violation" + register_from_string ~id:"STRICT_MODE_VIOLATION" ~hum:"Strict Mode Violation" [Starvation] let strong_self_not_checked = - register_from_string "STRONG_SELF_NOT_CHECKED" ~hum:"StrongSelf Not Checked" + register_from_string ~id:"STRONG_SELF_NOT_CHECKED" ~hum:"StrongSelf Not Checked" [SelfInBlock] let symexec_memory_error = - register_from_string "Symexec_memory_error" ~hum:"Symbolic Execution Memory Error" + register_from_string ~id:"Symexec_memory_error" ~hum:"Symbolic Execution Memory Error" + [Biabduction] -let thread_safety_violation = register_from_string "THREAD_SAFETY_VIOLATION" +let thread_safety_violation = register_from_string ~id:"THREAD_SAFETY_VIOLATION" [RacerD] let complexity_increase ~kind ~is_on_ui_thread = register_from_cost_string ~kind ~is_on_ui_thread "%s_COMPLEXITY_INCREASE" -let topl_error = register_from_string "TOPL_ERROR" +let topl_error = register_from_string ~id:"TOPL_ERROR" [TOPL] let unary_minus_applied_to_unsigned_expression = - register_from_string ~enabled:false "UNARY_MINUS_APPLIED_TO_UNSIGNED_EXPRESSION" + register_from_string ~enabled:false ~id:"UNARY_MINUS_APPLIED_TO_UNSIGNED_EXPRESSION" [Biabduction] + + +let uninitialized_value = register_from_string ~id:"UNINITIALIZED_VALUE" [Uninit] + +let unknown_proc = register_from_string ~id:"Unknown_proc" ~hum:"Unknown Procedure" [Biabduction] + +let unreachable_code_after = register_from_string ~id:"UNREACHABLE_CODE" [BufferOverrun] + +let use_after_delete = register_from_string ~id:"USE_AFTER_DELETE" [Pulse] + +let use_after_free = register_from_string ~id:"USE_AFTER_FREE" [Pulse] +let biabd_use_after_free = register_from_string ~id:"BIABD_USE_AFTER_FREE" [Biabduction] -let uninitialized_value = register_from_string "UNINITIALIZED_VALUE" +let use_after_lifetime = register_from_string ~id:"USE_AFTER_LIFETIME" [Pulse] -let unknown_proc = register_from_string "Unknown_proc" ~hum:"Unknown Procedure" +let user_controlled_sql_risk = register_from_string ~id:"USER_CONTROLLED_SQL_RISK" [Quandary] -let unreachable_code_after = register_from_string "UNREACHABLE_CODE" +let untrusted_buffer_access = + register_from_string ~enabled:false ~id:"UNTRUSTED_BUFFER_ACCESS" [Quandary] -let use_after_delete = register_from_string "USE_AFTER_DELETE" -let use_after_free = register_from_string "USE_AFTER_FREE" +let untrusted_deserialization = register_from_string ~id:"UNTRUSTED_DESERIALIZATION" [Quandary] -let biabd_use_after_free = register_from_string "BIABD_USE_AFTER_FREE" +let untrusted_deserialization_risk = + register_from_string ~id:"UNTRUSTED_DESERIALIZATION_RISK" [Quandary] -let use_after_lifetime = register_from_string "USE_AFTER_LIFETIME" -let user_controlled_sql_risk = register_from_string "USER_CONTROLLED_SQL_RISK" +let untrusted_environment_change_risk = + register_from_string ~id:"UNTRUSTED_ENVIRONMENT_CHANGE_RISK" [Quandary] -let untrusted_buffer_access = register_from_string ~enabled:false "UNTRUSTED_BUFFER_ACCESS" -let untrusted_deserialization = register_from_string "UNTRUSTED_DESERIALIZATION" +let untrusted_file = register_from_string ~id:"UNTRUSTED_FILE" [Quandary] -let untrusted_deserialization_risk = register_from_string "UNTRUSTED_DESERIALIZATION_RISK" +let untrusted_file_risk = register_from_string ~id:"UNTRUSTED_FILE_RISK" [Quandary] -let untrusted_environment_change_risk = register_from_string "UNTRUSTED_ENVIRONMENT_CHANGE_RISK" +let untrusted_heap_allocation = + register_from_string ~enabled:false ~id:"UNTRUSTED_HEAP_ALLOCATION" [Quandary] -let untrusted_file = register_from_string "UNTRUSTED_FILE" -let untrusted_file_risk = register_from_string "UNTRUSTED_FILE_RISK" +let untrusted_intent_creation = register_from_string ~id:"UNTRUSTED_INTENT_CREATION" [Quandary] -let untrusted_heap_allocation = register_from_string ~enabled:false "UNTRUSTED_HEAP_ALLOCATION" +let untrusted_url_risk = register_from_string ~id:"UNTRUSTED_URL_RISK" [Quandary] -let untrusted_intent_creation = register_from_string "UNTRUSTED_INTENT_CREATION" +let untrusted_variable_length_array = + register_from_string ~id:"UNTRUSTED_VARIABLE_LENGTH_ARRAY" [Quandary] -let untrusted_url_risk = register_from_string "UNTRUSTED_URL_RISK" -let untrusted_variable_length_array = register_from_string "UNTRUSTED_VARIABLE_LENGTH_ARRAY" +let vector_invalidation = register_from_string ~id:"VECTOR_INVALIDATION" [Pulse] -let vector_invalidation = register_from_string "VECTOR_INVALIDATION" +let weak_self_in_noescape_block = + register_from_string ~id:"WEAK_SELF_IN_NO_ESCAPE_BLOCK" [SelfInBlock] -let weak_self_in_noescape_block = register_from_string "WEAK_SELF_IN_NO_ESCAPE_BLOCK" let wrong_argument_number = - register_from_string "Wrong_argument_number" ~hum:"Wrong Argument Number" + register_from_string ~id:"Wrong_argument_number" ~hum:"Wrong Argument Number" [Biabduction] let unreachable_cost_call ~kind = diff --git a/infer/src/base/IssueType.mli b/infer/src/base/IssueType.mli index c15a72db5..dd8a626c2 100644 --- a/infer/src/base/IssueType.mli +++ b/infer/src/base/IssueType.mli @@ -10,6 +10,7 @@ open! IStd (** type of string used for localisation *) type t = private { unique_id: string + ; checkers: Checker.t list ; mutable enabled: bool ; mutable hum: string ; mutable doc_url: string option @@ -25,13 +26,24 @@ val pp : Format.formatter -> t -> unit (** pretty print a localised string *) val register_from_string : - ?enabled:bool -> ?hum:string -> ?doc_url:string -> ?linters_def_file:string -> string -> t + ?enabled:bool + -> ?hum:string + -> ?doc_url:string + -> ?linters_def_file:string + -> id:string + -> Checker.t list + -> t (** Create a new issue and register it in the list of all issues. NOTE: if the issue with the same string id is already registered, overrides `hum`, `doc_url`, and `linters_def_file`, but DOES NOT override `enabled`. This trick allows to deal with disabling/enabling dynamic AL issues from the config, when we don't know all params yet. Thus, the human-readable description can be updated when we encounter the definition of the issue type, eg in AL. *) +val checker_can_report : Checker.t -> t -> bool + [@@warning "-32"] +(** Whether the issue was registered as coming from the given checker. Important to call this before + reporting to keep documentation accurate. *) + val set_enabled : t -> bool -> unit val abduction_case_not_implemented : t diff --git a/infer/src/checkers/annotationReachability.ml b/infer/src/checkers/annotationReachability.ml index 2d402b99e..7d5076a38 100644 --- a/infer/src/checkers/annotationReachability.ml +++ b/infer/src/checkers/annotationReachability.ml @@ -330,7 +330,8 @@ module CxxAnnotationSpecs = struct (List.Assoc.find ~equal:String.equal spec_cfg "doc_url") in let linters_def_file = Option.value_map ~default:"" ~f:Fn.id Config.inferconfig_file in - IssueType.register_from_string spec_name ~doc_url ~linters_def_file + IssueType.register_from_string ~id:spec_name ~doc_url ~linters_def_file + [AnnotationReachability] in Reporting.log_error proc_desc err_log ~loc ~ltr:final_trace issue_type description in