diff --git a/infer/src/absint/IntraproceduralAnalysis.ml b/infer/src/absint/IntraproceduralAnalysis.ml new file mode 100644 index 000000000..c9a1d144e --- /dev/null +++ b/infer/src/absint/IntraproceduralAnalysis.ml @@ -0,0 +1,10 @@ +(* + * 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 + +type t = {proc_desc: Procdesc.t; tenv: Tenv.t; err_log: Errlog.t} diff --git a/infer/src/absint/IntraproceduralAnalysis.mli b/infer/src/absint/IntraproceduralAnalysis.mli new file mode 100644 index 000000000..7597f5369 --- /dev/null +++ b/infer/src/absint/IntraproceduralAnalysis.mli @@ -0,0 +1,12 @@ +(* + * 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 + +(** a subset of {!InterproceduralAnalysis.t} that doesn't have any inter-procedural callbacks and + cannot read summaries *) +type t = {proc_desc: Procdesc.t; tenv: Tenv.t; err_log: Errlog.t} diff --git a/infer/src/checkers/registerCheckers.ml b/infer/src/checkers/registerCheckers.ml index 74f931f31..e89b2b522 100644 --- a/infer/src/checkers/registerCheckers.ml +++ b/infer/src/checkers/registerCheckers.ml @@ -62,6 +62,24 @@ let dynamic_dispatch payload_field checker = DynamicDispatch (proc_callback_of_interprocedural payload_field checker) +let proc_callback_of_intraprocedural ?payload_field checker {Callbacks.summary; exe_env} = + let result = + checker + { IntraproceduralAnalysis.proc_desc= Summary.get_proc_desc summary + ; tenv= Exe_env.get_tenv exe_env (Summary.get_proc_name summary) + ; err_log= Summary.get_err_log summary } + in + match payload_field with + | None -> + summary + | Some payload_field -> + {summary with payloads= Field.fset payload_field summary.payloads result} + + +let intraprocedural_with_payload payload_field checker = + Procedure (proc_callback_of_intraprocedural ~payload_field checker) + + type callback = callback_fun * Language.t type checker = {name: string; active: bool; callbacks: callback list} @@ -150,7 +168,9 @@ let all_checkers = ; callbacks= [(Procedure InefficientKeysetIterator.checker, Language.Java)] } ; { name= "immutable cast" ; active= Config.is_checker_enabled ImmutableCast - ; callbacks= [(Procedure ImmutableChecker.callback_check_immutable_cast, Language.Java)] } + ; callbacks= + [ ( intraprocedural_with_payload Payloads.Fields.nullsafe ImmutableChecker.analyze + , Language.Java ) ] } ; { name= "fragment retains view" ; active= Config.is_checker_enabled FragmentRetainsView ; callbacks= @@ -158,7 +178,8 @@ let all_checkers = ; { name= "eradicate" ; active= Config.is_checker_enabled Eradicate ; callbacks= - [ (Procedure Eradicate.proc_callback, Language.Java) + [ ( intraprocedural_with_payload Payloads.Fields.nullsafe Eradicate.analyze_procedure + , Language.Java ) ; (File {callback= Eradicate.file_callback; issue_dir= NullsafeFileIssues}, Language.Java) ] } ; { name= "buffer overrun checker" diff --git a/infer/src/nullsafe/eradicate.ml b/infer/src/nullsafe/eradicate.ml index f1e3a5939..376506720 100644 --- a/infer/src/nullsafe/eradicate.ml +++ b/infer/src/nullsafe/eradicate.ml @@ -10,12 +10,6 @@ module L = Logging module F = Format open Dataflow -module Payload = SummaryPayload.Make (struct - type t = NullsafeSummary.t - - let field = Payloads.Fields.nullsafe -end) - let callback1 tenv find_canonical_duplicate calls_this checks idenv curr_pname curr_pdesc annotated_signature linereader proc_loc : bool * TypeState.t option = let add_formal typestate (param_signature : AnnotatedSignature.param_signature) = @@ -106,7 +100,7 @@ let callback1 tenv find_canonical_duplicate calls_this checks idenv curr_pname c (!calls_this, None) -let analyze_procedure tenv proc_name proc_desc calls_this checks annotated_signature linereader +let analyze_one_procedure tenv proc_name proc_desc calls_this checks annotated_signature linereader proc_loc : unit = let idenv = Idenv.create proc_desc in let find_duplicate_nodes = State.mk_find_duplicate_nodes proc_desc in @@ -194,18 +188,16 @@ let find_reason_to_skip_analysis proc_name proc_desc = (** Entry point for the nullsafe procedure-level analysis. *) -let callback checks {Callbacks.summary; exe_env} : Summary.t = - let proc_desc = Summary.get_proc_desc summary in +let analyze checks {IntraproceduralAnalysis.proc_desc; tenv} : NullsafeSummary.t option = let proc_name = Procdesc.get_proc_name proc_desc in L.debug Analysis Medium "Analysis of %a@\n" Procname.pp proc_name ; match find_reason_to_skip_analysis proc_name proc_desc with | Some reason -> L.debug Analysis Medium "Skipping analysis: %s@\n" reason ; - summary + None | None -> (* start the analysis! *) let calls_this = ref false in - let tenv = Exe_env.get_tenv exe_env proc_name in let annotated_signature = AnnotatedSignature.get_for_class_under_analysis tenv (Procdesc.get_attributes proc_desc) in @@ -218,24 +210,24 @@ let callback checks {Callbacks.summary; exe_env} : Summary.t = (* The main method - during this the actual analysis will happen and TypeErr will be populated with issues (and some of them - reported). *) - analyze_procedure tenv proc_name proc_desc calls_this checks annotated_signature linereader - loc ; + analyze_one_procedure tenv proc_name proc_desc calls_this checks annotated_signature + linereader loc ; (* Collect issues that were detected during analysis and put them in summary for further processing *) let issues = TypeErr.get_errors () |> List.map ~f:(fun (issues, _) -> issues) in (* Report errors of "farall" class - those could not be reported during analysis phase. *) TypeErr.report_forall_issues_and_reset (EradicateCheckers.report_error tenv) ~nullsafe_mode:annotated_signature.nullsafe_mode proc_desc ; - Payload.update_summary NullsafeSummary.{issues} summary + Some {NullsafeSummary.issues} -let proc_callback = +let analyze_procedure analysis_data = let checks = {TypeCheck.eradicate= true; check_ret_type= []} in - callback checks + analyze checks analysis_data let file_callback = FileLevelAnalysis.analyze_file -let callback_check_return_type check_return_type callback_args = +let analyze_for_immutable_cast_checker check_return_type analysis_data = let checks = {TypeCheck.eradicate= false; check_ret_type= [check_return_type]} in - callback checks callback_args + analyze checks analysis_data diff --git a/infer/src/nullsafe/eradicate.mli b/infer/src/nullsafe/eradicate.mli index ad239a47b..c1229a83b 100644 --- a/infer/src/nullsafe/eradicate.mli +++ b/infer/src/nullsafe/eradicate.mli @@ -9,13 +9,14 @@ open! IStd (** The main entry point for Nullsafe typechecker. *) -val proc_callback : Callbacks.proc_callback_t +val analyze_procedure : IntraproceduralAnalysis.t -> NullsafeSummary.t option (** Proc-level callback for nullsafe. *) val file_callback : Callbacks.file_callback_t (** File-level callback for nullsafe. Is called after all proc-level callbacks are called and calculated their summaries *) -val callback_check_return_type : TypeCheck.check_return_type -> Callbacks.proc_callback_t +val analyze_for_immutable_cast_checker : + TypeCheck.check_return_type -> IntraproceduralAnalysis.t -> NullsafeSummary.t option (** For checkers that explore eradicate/nullsafe infra, but not part of nullsafe.Annot Call the given check_return_type at the end of every procedure. *) diff --git a/infer/src/nullsafe/immutableChecker.ml b/infer/src/nullsafe/immutableChecker.ml index eb25a175c..53b4e0c44 100644 --- a/infer/src/nullsafe/immutableChecker.ml +++ b/infer/src/nullsafe/immutableChecker.ml @@ -43,6 +43,5 @@ let check_immutable_cast tenv curr_pname curr_pdesc typ_expected typ_found_opt l () -let callback_check_immutable_cast ({Callbacks.exe_env; summary} as args) = - let tenv = Exe_env.get_tenv exe_env (Summary.get_proc_name summary) in - Eradicate.callback_check_return_type (check_immutable_cast tenv) args +let analyze ({IntraproceduralAnalysis.tenv} as analysis_data) = + Eradicate.analyze_for_immutable_cast_checker (check_immutable_cast tenv) analysis_data diff --git a/infer/src/nullsafe/immutableChecker.mli b/infer/src/nullsafe/immutableChecker.mli index 36dca9fac..abe337129 100644 --- a/infer/src/nullsafe/immutableChecker.mli +++ b/infer/src/nullsafe/immutableChecker.mli @@ -7,4 +7,4 @@ open! IStd -val callback_check_immutable_cast : Callbacks.proc_callback_t +val analyze : IntraproceduralAnalysis.t -> NullsafeSummary.t option