[docs] add checker to issue types

Summary:
The eventual goal is to document issue types and checkers better, in
particular which issue types "belong" to which checkers. (note:
Currently some issue types are reported by several checkers.)

The plan is to associate a list of "allowed" checkers to each issue type
and (not in this diff) raise a runtime exception if a checker not in
that list tries to report that issue. Hopefully tests cover all the use
cases and there are no surprises. I've filled in the lists by
`git grep`ing which checkers used which issue types in their code.

Reviewed By: ngorogiannis

Differential Revision: D21617622

fbshipit-source-id: 159ab171f
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent f8e71ceb1e
commit a5203ced4e

@ -241,7 +241,7 @@ let recognize_exception exn =
; severity= None ; severity= None
; category= Nocat } ; category= Nocat }
| Custom_error (error_msg, desc) -> | Custom_error (error_msg, desc) ->
{ name= IssueType.register_from_string error_msg { name= IssueType.register_from_string ~id:error_msg [Biabduction]
; description= desc ; description= desc
; ocaml_pos= None ; ocaml_pos= None
; visibility= Exn_user ; visibility= Exn_user
@ -362,7 +362,7 @@ let recognize_exception exn =
; category= Nocat } ; category= Nocat }
| Java_runtime_exception (exn_name, _, desc) -> | Java_runtime_exception (exn_name, _, desc) ->
let exn_str = Typ.Name.name exn_name in 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 ; description= desc
; ocaml_pos= None ; ocaml_pos= None
; visibility= Exn_user ; visibility= Exn_user

@ -262,8 +262,8 @@ let create_parsed_linters linters_def_file checkers : linter list =
(Config.get_linter_doc_url ~linter_id:checker.id) (Config.get_linter_doc_url ~linter_id:checker.id)
issue_desc.issue_type.doc_url issue_desc.issue_type.doc_url
in in
IssueType.register_from_string checker.id ?hum:issue_desc.issue_type.name ?doc_url IssueType.register_from_string ~id:checker.id ?hum:issue_desc.issue_type.name ?doc_url
~linters_def_file ~linters_def_file [Linters]
in in
let issue_desc = {issue_desc with issue_type} in let issue_desc = {issue_desc with issue_type} in
L.(debug Linters Medium) "@\nIssue_desc = %a@\n" CIssue.pp_issue issue_desc ; L.(debug Linters Medium) "@\nIssue_desc = %a@\n" CIssue.pp_issue issue_desc ;

@ -138,7 +138,7 @@ let all_checkers =
} }
; (* toy resource analysis to use in the infer lab, see the lab/ directory *) ; (* toy resource analysis to use in the infer lab, see the lab/ directory *)
{ name= "resource leak" { name= "resource leak"
; active= Config.is_checker_enabled ResourceLeak ; active= Config.is_checker_enabled ResourceLeakLabExercise
; callbacks= ; callbacks=
[ ( (* the checked-in version is intraprocedural, but the lab asks to make it [ ( (* the checked-in version is intraprocedural, but the lab asks to make it
interprocedural later on *) interprocedural later on *)

@ -28,7 +28,7 @@ type t =
| Purity | Purity
| Quandary | Quandary
| RacerD | RacerD
| ResourceLeak | ResourceLeakLabExercise
| SIOF | SIOF
| SelfInBlock | SelfInBlock
| Starvation | Starvation
@ -214,7 +214,7 @@ let config checker =
; cli_flag= "racerd" ; cli_flag= "racerd"
; enabled_by_default= true ; enabled_by_default= true
; cli_deprecated_flags= ["-threadsafety"] } ; cli_deprecated_flags= ["-threadsafety"] }
| ResourceLeak -> | ResourceLeakLabExercise ->
{ support= (fun _ -> ToySupport) { support= (fun _ -> ToySupport)
; short_documentation= "" ; short_documentation= ""
; show_in_help= false ; show_in_help= false

@ -28,7 +28,7 @@ type t =
| Purity | Purity
| Quandary | Quandary
| RacerD | RacerD
| ResourceLeak | ResourceLeakLabExercise
| SIOF | SIOF
| SelfInBlock | SelfInBlock
| Starvation | Starvation

@ -1169,7 +1169,7 @@ and () =
let (_ : string list ref) = let (_ : string list ref) =
CLOpt.mk_string_list ?deprecated ~long CLOpt.mk_string_list ?deprecated ~long
~f:(fun issue_id -> ~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 ; IssueType.set_enabled issue b ;
issue_id ) issue_id )
?default ~meta:"issue_type" ?default ~meta:"issue_type"

@ -11,6 +11,7 @@ open! IStd
module Unsafe : sig module Unsafe : sig
type t = private type t = private
{ unique_id: string { unique_id: string
; checkers: Checker.t list
; mutable enabled: bool ; mutable enabled: bool
; mutable hum: string ; mutable hum: string
; mutable doc_url: string option ; mutable doc_url: string option
@ -20,7 +21,13 @@ module Unsafe : sig
val equal : t -> t -> bool val equal : t -> t -> bool
val register_from_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
val register_from_cost_string : val register_from_cost_string :
?enabled:bool ?enabled:bool
@ -36,6 +43,7 @@ end = struct
module T = struct module T = struct
type t = type t =
{ unique_id: string { unique_id: string
; checkers: Checker.t list
; mutable enabled: bool ; mutable enabled: bool
; mutable hum: string ; mutable hum: string
; mutable doc_url: string option ; 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 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 definitely. The [hum]an-readable description can be updated when we encounter the definition
of the issue type, eg in AL. *) 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 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 try
let old = IssueSet.find issue !all_issues in let old = IssueSet.find issue !all_issues in
(* update human-readable string in case it was supplied this time, but keep the previous (* 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_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 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 let all_issues () = IssueSet.elements !all_issues
@ -102,204 +111,232 @@ include Unsafe
(** pretty print a localised string *) (** pretty print a localised string *)
let pp fmt t = Format.pp_print_string fmt t.unique_id 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 = 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 = 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 = 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 = let checkers_expensive_overrides_unexpensive =
register_from_string "CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED" register_from_string ~id:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED"
~hum:"Expensive Overrides Unannotated" ~hum:"Expensive Overrides Unannotated" [AnnotationReachability]
let checkers_fragment_retain_view = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 *) (* TODO(T54070503) remove condition redundant nonnull *)
let _ = 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 = 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 = 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 = 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 = let eradicate_inconsistent_subclass_parameter_annotation =
register_from_string "ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION" register_from_string ~id:"ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION"
~hum:"Inconsistent Subclass Parameter Annotation" ~hum:"Inconsistent Subclass Parameter Annotation" [Eradicate]
let eradicate_inconsistent_subclass_return_annotation = let eradicate_inconsistent_subclass_return_annotation =
register_from_string "ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION" register_from_string ~id:"ERADICATE_INCONSISTENT_SUBCLASS_RETURN_ANNOTATION"
~hum:"Inconsistent Subclass Return Annotation" ~hum:"Inconsistent Subclass Return Annotation" [Eradicate]
let eradicate_redundant_nested_class_annotation = let eradicate_redundant_nested_class_annotation =
register_from_string "ERADICATE_REDUNDANT_NESTED_CLASS_ANNOTATION" register_from_string ~id:"ERADICATE_REDUNDANT_NESTED_CLASS_ANNOTATION"
~hum:"@Nullsafe annotation is redundant" ~hum:"@Nullsafe annotation is redundant" [Eradicate]
let eradicate_bad_nested_class_annotation = let eradicate_bad_nested_class_annotation =
register_from_string "ERADICATE_BAD_NESTED_CLASS_ANNOTATION" register_from_string ~id:"ERADICATE_BAD_NESTED_CLASS_ANNOTATION"
~hum:"@Nullsafe annotation is inconsistent with outer class" ~hum:"@Nullsafe annotation is inconsistent with outer class" [Eradicate]
let eradicate_nullable_dereference = 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 = 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 = 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 = 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 = let eradicate_unchecked_usage_in_nullsafe =
register_from_string "ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE" register_from_string ~id:"ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE"
~hum:"Nullsafe mode: unchecked usage of a value" ~hum:"Nullsafe mode: unchecked usage of a value" [Eradicate]
let eradicate_unvetted_third_party_in_nullsafe = let eradicate_unvetted_third_party_in_nullsafe =
register_from_string "ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE" register_from_string ~id:"ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE"
~hum:"Nullsafe mode: unchecked usage of unvetted third-party" ~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, (* Meta issues in eradicate are technical issues reflecting null-safety state of classes in general,
in contrast with concrete nullability type violations *) in contrast with concrete nullability type violations *)
let eradicate_meta_class_is_nullsafe = let eradicate_meta_class_is_nullsafe =
register_from_string "ERADICATE_META_CLASS_IS_NULLSAFE" register_from_string ~id:"ERADICATE_META_CLASS_IS_NULLSAFE"
~hum: ~hum:
"Class is marked @Nullsafe and has 0 issues" (* Should be enabled for special integrations *) "Class is marked @Nullsafe and has 0 issues" (* Should be enabled for special integrations *)
~enabled:false ~enabled:false [Eradicate]
(* Class is either: (* 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. - has at least one (currently possibly hidden) issue in order to be marked as @Nullsafe.
*) *)
let eradicate_meta_class_needs_improvement = let eradicate_meta_class_needs_improvement =
register_from_string "ERADICATE_META_CLASS_NEEDS_IMPROVEMENT" register_from_string ~id:"ERADICATE_META_CLASS_NEEDS_IMPROVEMENT"
~hum: ~hum:
"Class needs improvement to become @Nullsafe" (* Should be enabled for special integrations *) "Class needs improvement to become @Nullsafe" (* Should be enabled for special integrations *)
~enabled:false ~enabled:false [Eradicate]
let eradicate_meta_class_can_be_nullsafe = 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: ~hum:
"Class has 0 issues and can be marked @Nullsafe" "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 = let expensive_cost_call ~kind ~is_on_ui_thread =
register_from_cost_string ~enabled:false ~kind ~is_on_ui_thread "EXPENSIVE_%s" 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 *) (* from AL default linters *)
let _global_variable_initialized_with_function_or_method_call = 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 = 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 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 = 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 = 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 = 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 = 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 = 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 = 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 = let complexity_increase ~kind ~is_on_ui_thread =
register_from_cost_string ~kind ~is_on_ui_thread "%s_COMPLEXITY_INCREASE" 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 = 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 = 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 = let unreachable_cost_call ~kind =

@ -10,6 +10,7 @@ open! IStd
(** type of string used for localisation *) (** type of string used for localisation *)
type t = private type t = private
{ unique_id: string { unique_id: string
; checkers: Checker.t list
; mutable enabled: bool ; mutable enabled: bool
; mutable hum: string ; mutable hum: string
; mutable doc_url: string option ; mutable doc_url: string option
@ -25,13 +26,24 @@ val pp : Format.formatter -> t -> unit
(** pretty print a localised string *) (** pretty print a localised string *)
val register_from_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 (** 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 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 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 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. *) 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 set_enabled : t -> bool -> unit
val abduction_case_not_implemented : t val abduction_case_not_implemented : t

@ -330,7 +330,8 @@ module CxxAnnotationSpecs = struct
(List.Assoc.find ~equal:String.equal spec_cfg "doc_url") (List.Assoc.find ~equal:String.equal spec_cfg "doc_url")
in in
let linters_def_file = Option.value_map ~default:"" ~f:Fn.id Config.inferconfig_file 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 in
Reporting.log_error proc_desc err_log ~loc ~ltr:final_trace issue_type description Reporting.log_error proc_desc err_log ~loc ~ltr:final_trace issue_type description
in in

Loading…
Cancel
Save