[nullsafe] make eradicate an Intraprocedural.t

Summary: On our way to making nullsafe its own dune library.

Reviewed By: mityal

Differential Revision: D21351454

fbshipit-source-id: a630cff95
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent a11791d5fc
commit d8d38655b1

@ -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}

@ -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}

@ -62,6 +62,24 @@ let dynamic_dispatch payload_field checker =
DynamicDispatch (proc_callback_of_interprocedural 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 callback = callback_fun * Language.t
type checker = {name: string; active: bool; callbacks: callback list} type checker = {name: string; active: bool; callbacks: callback list}
@ -150,7 +168,9 @@ let all_checkers =
; callbacks= [(Procedure InefficientKeysetIterator.checker, Language.Java)] } ; callbacks= [(Procedure InefficientKeysetIterator.checker, Language.Java)] }
; { name= "immutable cast" ; { name= "immutable cast"
; active= Config.is_checker_enabled ImmutableCast ; 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" ; { name= "fragment retains view"
; active= Config.is_checker_enabled FragmentRetainsView ; active= Config.is_checker_enabled FragmentRetainsView
; callbacks= ; callbacks=
@ -158,7 +178,8 @@ let all_checkers =
; { name= "eradicate" ; { name= "eradicate"
; active= Config.is_checker_enabled Eradicate ; active= Config.is_checker_enabled Eradicate
; callbacks= ; 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) ; (File {callback= Eradicate.file_callback; issue_dir= NullsafeFileIssues}, Language.Java)
] } ] }
; { name= "buffer overrun checker" ; { name= "buffer overrun checker"

@ -10,12 +10,6 @@ module L = Logging
module F = Format module F = Format
open Dataflow 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 let callback1 tenv find_canonical_duplicate calls_this checks idenv curr_pname curr_pdesc
annotated_signature linereader proc_loc : bool * TypeState.t option = annotated_signature linereader proc_loc : bool * TypeState.t option =
let add_formal typestate (param_signature : AnnotatedSignature.param_signature) = 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) (!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 = proc_loc : unit =
let idenv = Idenv.create proc_desc in let idenv = Idenv.create proc_desc in
let find_duplicate_nodes = State.mk_find_duplicate_nodes 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. *) (** Entry point for the nullsafe procedure-level analysis. *)
let callback checks {Callbacks.summary; exe_env} : Summary.t = let analyze checks {IntraproceduralAnalysis.proc_desc; tenv} : NullsafeSummary.t option =
let proc_desc = Summary.get_proc_desc summary in
let proc_name = Procdesc.get_proc_name proc_desc in let proc_name = Procdesc.get_proc_name proc_desc in
L.debug Analysis Medium "Analysis of %a@\n" Procname.pp proc_name ; L.debug Analysis Medium "Analysis of %a@\n" Procname.pp proc_name ;
match find_reason_to_skip_analysis proc_name proc_desc with match find_reason_to_skip_analysis proc_name proc_desc with
| Some reason -> | Some reason ->
L.debug Analysis Medium "Skipping analysis: %s@\n" reason ; L.debug Analysis Medium "Skipping analysis: %s@\n" reason ;
summary None
| None -> | None ->
(* start the analysis! *) (* start the analysis! *)
let calls_this = ref false in let calls_this = ref false in
let tenv = Exe_env.get_tenv exe_env proc_name in
let annotated_signature = let annotated_signature =
AnnotatedSignature.get_for_class_under_analysis tenv (Procdesc.get_attributes proc_desc) AnnotatedSignature.get_for_class_under_analysis tenv (Procdesc.get_attributes proc_desc)
in 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 (* The main method - during this the actual analysis will happen and TypeErr will be populated with
issues (and some of them - reported). issues (and some of them - reported).
*) *)
analyze_procedure tenv proc_name proc_desc calls_this checks annotated_signature linereader analyze_one_procedure tenv proc_name proc_desc calls_this checks annotated_signature
loc ; linereader loc ;
(* Collect issues that were detected during analysis and put them in summary for further processing *) (* 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 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. *) (* Report errors of "farall" class - those could not be reported during analysis phase. *)
TypeErr.report_forall_issues_and_reset TypeErr.report_forall_issues_and_reset
(EradicateCheckers.report_error tenv) (EradicateCheckers.report_error tenv)
~nullsafe_mode:annotated_signature.nullsafe_mode proc_desc ; ~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 let checks = {TypeCheck.eradicate= true; check_ret_type= []} in
callback checks analyze checks analysis_data
let file_callback = FileLevelAnalysis.analyze_file 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 let checks = {TypeCheck.eradicate= false; check_ret_type= [check_return_type]} in
callback checks callback_args analyze checks analysis_data

@ -9,13 +9,14 @@ open! IStd
(** The main entry point for Nullsafe typechecker. *) (** 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. *) (** Proc-level callback for nullsafe. *)
val file_callback : Callbacks.file_callback_t val file_callback : Callbacks.file_callback_t
(** File-level callback for nullsafe. Is called after all proc-level callbacks are called and (** File-level callback for nullsafe. Is called after all proc-level callbacks are called and
calculated their summaries *) 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 (** 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. *) given check_return_type at the end of every procedure. *)

@ -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 analyze ({IntraproceduralAnalysis.tenv} as analysis_data) =
let tenv = Exe_env.get_tenv exe_env (Summary.get_proc_name summary) in Eradicate.analyze_for_immutable_cast_checker (check_immutable_cast tenv) analysis_data
Eradicate.callback_check_return_type (check_immutable_cast tenv) args

@ -7,4 +7,4 @@
open! IStd open! IStd
val callback_check_immutable_cast : Callbacks.proc_callback_t val analyze : IntraproceduralAnalysis.t -> NullsafeSummary.t option

Loading…
Cancel
Save