Introduce method SummaryPayload.read_toplevel_procedure

Summary:
Cluster checkers call `SummaryPayload.read` but set the `caller_summary` to correspond to the same summary as gives the `callee_pname`

This change introduces a new method `read_toplevel_procedure` that does not require a `caller_summary`, to be used by the cluster checkers

Reviewed By: ngorogiannis

Differential Revision: D16131660

fbshipit-source-id: 12caa1000
master
Phoebe Nichols 5 years ago committed by Facebook Github Bot
parent b5b8259ea7
commit d9535f42d5

@ -20,9 +20,12 @@ module type S = sig
val of_summary : Summary.t -> t option
val read_full : Procdesc.t -> Typ.Procname.t -> (Procdesc.t * t) option
val read_full :
caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> (Procdesc.t * t) option
val read : Procdesc.t -> Typ.Procname.t -> t option
val read : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> t option
val read_toplevel_procedure : Typ.Procname.t -> t option
end
module Make (P : Payload) : S with type t = P.t = struct
@ -38,16 +41,21 @@ module Make (P : Payload) : S with type t = P.t = struct
let of_summary (summary : Summary.t) = of_payloads summary.payloads
let read_full caller_pdesc callee_pname =
let read_all ?caller_summary ~callee_pname =
let open Option.Monad_infix in
Ondemand.analyze_proc_name ~caller_pdesc callee_pname
Ondemand.analyze_proc_name
?caller_pdesc:(Option.map ~f:Summary.get_proc_desc caller_summary)
callee_pname
>>= fun summary ->
of_summary summary
>>| fun payload ->
(* we could return the proc_desc if some client needed this but this would complicate the return
type so for now let's not do that *)
(Summary.get_proc_desc summary, payload)
of_summary summary >>| fun payload -> (Summary.get_proc_desc summary, payload)
let read_full ~caller_summary ~callee_pname = read_all ~caller_summary ~callee_pname
let read ~caller_summary ~callee_pname =
read_all ~caller_summary ~callee_pname |> Option.map ~f:snd
let read caller_pdesc callee_pname = read_full caller_pdesc callee_pname |> Option.map ~f:snd
let read_toplevel_procedure callee_pname =
read_all ?caller_summary:None ~callee_pname |> Option.map ~f:snd
end

@ -22,13 +22,15 @@ module type S = sig
val of_summary : Summary.t -> t option
(** Read the corresponding part of the payload from the procedure summary *)
val read_full : Procdesc.t -> Typ.Procname.t -> (Procdesc.t * t) option
[@@warning "-32"]
val read_full :
caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> (Procdesc.t * t) option
(** Return the proc desc and payload for the given procedure. Runs the analysis on-demand if
necessary. *)
val read : Procdesc.t -> Typ.Procname.t -> t option
val read : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> t option
(** Return the payload for the given procedure. Runs the analysis on-demand if necessary. *)
val read_toplevel_procedure : Typ.Procname.t -> t option
end
module Make (P : Payload) : S with type t = P.t

@ -19,7 +19,7 @@ type proc_callback_args =
type proc_callback_t = proc_callback_args -> Summary.t
type cluster_callback_args =
{procedures: (Tenv.t * Procdesc.t) list; source_file: SourceFile.t; exe_env: Exe_env.t}
{procedures: (Tenv.t * Summary.t) list; source_file: SourceFile.t; exe_env: Exe_env.t}
type cluster_callback_t = cluster_callback_args -> unit
@ -46,7 +46,7 @@ let get_procedure_definition exe_env proc_name =
Procdesc.load proc_name
|> Option.map ~f:(fun proc_desc ->
let tenv = Exe_env.get_tenv exe_env proc_name in
(tenv, proc_desc) )
(tenv, Summary.reset proc_desc) )
(** Invoke all registered procedure callbacks on the given procedure. *)
@ -91,8 +91,8 @@ let iterate_cluster_callbacks all_procs exe_env source_file =
let environment = {procedures; source_file; exe_env} in
let language_matches language =
match procedures with
| (_, pdesc) :: _ ->
Language.equal language (Typ.Procname.get_language (Procdesc.get_proc_name pdesc))
| (_, summary) :: _ ->
Language.equal language (Typ.Procname.get_language (Summary.get_proc_name summary))
| _ ->
true
in

@ -24,7 +24,7 @@ type proc_callback_args =
type proc_callback_t = proc_callback_args -> Summary.t
type cluster_callback_args =
{procedures: (Tenv.t * Procdesc.t) list; source_file: SourceFile.t; exe_env: Exe_env.t}
{procedures: (Tenv.t * Summary.t) list; source_file: SourceFile.t; exe_env: Exe_env.t}
type cluster_callback_t = cluster_callback_args -> unit

@ -216,7 +216,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
, _
, _ ) ->
let domain_summary =
Payload.read (Summary.get_proc_desc proc_data.summary) callee_procname
Payload.read ~caller_summary:proc_data.summary ~callee_pname:callee_procname
in
let receiver =
Domain.LocalAccessPath.make
@ -247,7 +247,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
(* treat it like a normal call *)
apply_callee_summary domain_summary caller_pname return_base actuals astate
| Call (ret_id_typ, Direct callee_procname, actuals, _, _) ->
let summary = Payload.read (Summary.get_proc_desc proc_data.summary) callee_procname in
let summary =
Payload.read ~caller_summary:proc_data.summary ~callee_pname:callee_procname
in
apply_callee_summary summary caller_pname ret_id_typ actuals astate
| Assign (lhs_ae, HilExp.AccessExpression rhs_ae, _) -> (
(* creating an alias for the rhs binding; assume all reads will now occur through the

@ -69,9 +69,12 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
type extras = ProcData.no_extras
let is_compile_time_constructed pdesc pv =
let is_compile_time_constructed summary pv =
let init_pname = Pvar.get_initializer_pname pv in
match Option.bind init_pname ~f:(Payload.read pdesc) with
match
Option.bind init_pname ~f:(fun callee_pname ->
Payload.read ~caller_summary:summary ~callee_pname )
with
| Some (Bottom, _) ->
(* we analyzed the initializer for this global and found that it doesn't require any runtime
initialization so cannot participate in SIOF *)
@ -94,13 +97,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
Staged.unstage (filter_global_accesses (Domain.VarNames.of_list always_initialized))
let get_globals pdesc e =
let get_globals summary e =
let is_dangerous_global pv =
Pvar.is_global pv
&& (not (Pvar.is_static_local pv))
&& (not (Pvar.is_pod pv))
&& (not (Pvar.is_compile_constant pv))
&& (not (is_compile_time_constructed pdesc pv))
&& (not (is_compile_time_constructed summary pv))
&& is_not_always_initialized pv
in
Exp.program_vars e
@ -127,20 +130,19 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
(NonBottom trace_with_non_init_globals, snd astate)
let add_actuals_globals astate0 pdesc call_loc actuals =
let add_actuals_globals astate0 summary call_loc actuals =
List.fold_left actuals ~init:astate0 ~f:(fun astate (e, _) ->
get_globals pdesc e |> add_globals astate call_loc )
get_globals summary e |> add_globals astate call_loc )
let at_least_nonbottom = Domain.join (NonBottom SiofTrace.bottom, Domain.VarNames.empty)
let exec_instr astate {ProcData.summary} _ (instr : Sil.instr) =
let pdesc = Summary.get_proc_desc summary in
match instr with
| Store (Lvar global, Typ.{desc= Tptr _}, Lvar _, loc)
when (Option.equal Typ.Procname.equal)
(Pvar.get_initializer_pname global)
(Some (Procdesc.get_proc_name pdesc)) ->
(Some (Summary.get_proc_name summary)) ->
(* if we are just taking the reference of another global then we are not really accessing
it. This is a dumb heuristic as something also might take that result and then
dereference it, thus requiring the target object to be initialized. Solving this would
@ -152,7 +154,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| Load (_, exp, _, loc) (* dereference -> add all the dangerous variables *)
| Store (_, _, exp, loc) (* except in the case above, consider all reads as dangerous *)
| Prune (exp, loc, _, _) ->
get_globals pdesc exp |> add_globals astate loc
get_globals summary exp |> add_globals astate loc
| Call (_, Const (Cfun callee_pname), _, _, _) when is_whitelisted callee_pname ->
at_least_nonbottom astate
| Call (_, Const (Cfun callee_pname), _, _, _) when is_modelled callee_pname ->
@ -169,10 +171,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| Call (_, Const (Cfun (ObjC_Cpp cpp_pname as callee_pname)), _ :: actuals_without_self, loc, _)
when Typ.Procname.is_constructor callee_pname && Typ.Procname.ObjC_Cpp.is_constexpr cpp_pname
->
add_actuals_globals astate pdesc loc actuals_without_self
add_actuals_globals astate summary loc actuals_without_self
| Call (_, Const (Cfun callee_pname), actuals, loc, _) ->
let callee_astate =
match Payload.read pdesc callee_pname with
match Payload.read ~caller_summary:summary ~callee_pname with
| Some (NonBottom trace, initialized_by_callee) ->
let already_initialized = snd astate in
let dangerous_accesses =
@ -193,12 +195,12 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| None ->
(Bottom, Domain.VarNames.empty)
in
add_actuals_globals astate pdesc loc actuals
add_actuals_globals astate summary loc actuals
|> Domain.join callee_astate
|> (* make sure it's not Bottom: we made a function call so this needs initialization *)
at_least_nonbottom
| Call (_, _, actuals, loc, _) ->
add_actuals_globals astate pdesc loc actuals
add_actuals_globals astate summary loc actuals
|> (* make sure it's not Bottom: we made a function call so this needs initialization *)
at_least_nonbottom
| Metadata _ ->
@ -218,9 +220,9 @@ let is_foreign current_tu v =
true
let report_siof summary trace pdesc gname loc =
let report_siof summary trace gname loc =
let trace_of_pname pname =
match Payload.read pdesc pname with
match Payload.read ~caller_summary:summary ~callee_pname:pname with
| Some (NonBottom summary, _) ->
summary
| _ ->
@ -244,7 +246,8 @@ let report_siof summary trace pdesc gname loc =
else List.iter ~f:report_one_path reportable_paths
let siof_check pdesc gname (summary : Summary.t) =
let siof_check gname (summary : Summary.t) =
let pdesc = Summary.get_proc_desc summary in
match summary.payloads.siof with
| Some (NonBottom post, _) ->
let attrs = Procdesc.get_attributes pdesc in
@ -260,7 +263,7 @@ let siof_check pdesc gname (summary : Summary.t) =
if not (SiofTrace.Sinks.is_empty foreign_sinks) then
report_siof summary
(SiofTrace.update_sinks post foreign_sinks)
pdesc gname attrs.ProcAttributes.loc
gname attrs.ProcAttributes.loc
| Some (Bottom, _) | None ->
()
@ -310,7 +313,7 @@ let checker {Callbacks.tenv; summary; get_procs_in_file} : Summary.t =
in
( match Typ.Procname.get_global_name_of_initializer pname with
| Some gname ->
siof_check proc_desc gname updated_summary
siof_check gname updated_summary
| None ->
() ) ;
updated_summary

@ -567,15 +567,15 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
specs
let merge_callee_map call_site pdesc callee_pname tenv specs astate =
match Payload.read pdesc callee_pname with
let merge_callee_map call_site summary callee_pname tenv specs astate =
match Payload.read ~caller_summary:summary ~callee_pname with
| None ->
astate
| Some callee_call_map ->
let add_call_site annot sink calls astate =
if AnnotReachabilityDomain.CallSites.is_empty calls then astate
else
let pname = Procdesc.get_proc_name pdesc in
let pname = Summary.get_proc_name summary in
List.fold
~f:(fun astate (spec : AnnotationSpec.t) ->
if spec.sanitizer_predicate tenv pname then astate
@ -592,11 +592,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| Sil.Call ((id, _), Const (Cfun callee_pname), _, _, _) when is_unlikely callee_pname ->
Domain.add_tracking_var (Var.of_id id) astate
| Sil.Call (_, Const (Cfun callee_pname), _, call_loc, _) ->
let pdesc = Summary.get_proc_desc summary in
let caller_pname = Procdesc.get_proc_name pdesc in
let caller_pname = Summary.get_proc_name summary in
let call_site = CallSite.make callee_pname call_loc in
check_call tenv callee_pname caller_pname call_site astate extras
|> merge_callee_map call_site pdesc callee_pname tenv extras
|> merge_callee_map call_site summary callee_pname tenv extras
| Sil.Load (id, exp, _, _) when is_tracking_exp astate exp ->
Domain.add_tracking_var (Var.of_id id) astate
| Sil.Store (Exp.Lvar pvar, _, exp, _) when is_tracking_exp astate exp ->

@ -22,12 +22,13 @@ module Payload = SummaryPayload.Make (struct
let field = Payloads.Fields.class_loads
end)
let do_call pdesc callee loc init =
Payload.read pdesc callee |> Option.fold ~init ~f:(ClassLoadsDomain.integrate_summary callee loc)
let do_call summary callee loc init =
Payload.read ~caller_summary:summary ~callee_pname:callee
|> Option.fold ~init ~f:(ClassLoadsDomain.integrate_summary callee loc)
(** fully load a class given the typename *)
let rec load_class proc_desc tenv loc astate class_name =
let rec load_class summary tenv loc astate class_name =
(* don't bother if class is already loaded *)
if ClassLoadsDomain.mem_typename class_name astate then astate
else
@ -37,78 +38,78 @@ let rec load_class proc_desc tenv loc astate class_name =
let astate2 =
let class_initializer = Typ.Procname.(Java (Java.get_class_initializer class_name)) in
(* NB may recurse if we are in class init but the shortcircuiting above makes it a no-op *)
do_call proc_desc class_initializer loc astate1
do_call summary class_initializer loc astate1
in
(* finally, recursively load all superclasses *)
Tenv.lookup tenv class_name
|> Option.value_map ~default:[] ~f:(fun tstruct -> tstruct.Typ.Struct.supers)
|> List.fold ~init:astate2 ~f:(load_class proc_desc tenv loc)
|> List.fold ~init:astate2 ~f:(load_class summary tenv loc)
let load_type proc_desc tenv loc (typ : Typ.t) astate =
let load_type summary tenv loc (typ : Typ.t) astate =
match typ with
| {desc= Tstruct name} | {desc= Tptr ({desc= Tstruct name}, _)} ->
load_class proc_desc tenv loc astate name
load_class summary tenv loc astate name
| _ ->
astate
let rec load_array proc_desc tenv loc (typ : Typ.t) astate =
let rec load_array summary tenv loc (typ : Typ.t) astate =
match typ with
| {desc= Tarray {elt}} ->
load_array proc_desc tenv loc elt astate
load_array summary tenv loc elt astate
| _ ->
load_type proc_desc tenv loc typ astate
load_type summary tenv loc typ astate
let rec add_loads_of_exp proc_desc tenv loc (exp : Exp.t) astate =
let rec add_loads_of_exp summary tenv loc (exp : Exp.t) astate =
match exp with
| Const (Cclass class_ident) ->
(* [X.class] expressions *)
let class_str = Ident.name_to_string class_ident |> Mangled.from_string in
let class_name = Typ.JavaClass class_str in
load_class proc_desc tenv loc astate class_name
load_class summary tenv loc astate class_name
| Sizeof {typ= {desc= Tarray {elt}}} ->
(* anewarray / multinewarray *)
load_array proc_desc tenv loc elt astate
load_array summary tenv loc elt astate
| Cast (_, e) | UnOp (_, e, _) | Exn e ->
(* NB Cast is only used for primitive types *)
add_loads_of_exp proc_desc tenv loc e astate
add_loads_of_exp summary tenv loc e astate
| BinOp (_, e1, e2) ->
add_loads_of_exp proc_desc tenv loc e1 astate |> add_loads_of_exp proc_desc tenv loc e2
add_loads_of_exp summary tenv loc e1 astate |> add_loads_of_exp summary tenv loc e2
| Lfield (e, _, typ') ->
(* getfield / getstatic / putfield / putstatic *)
load_type proc_desc tenv loc typ' astate |> add_loads_of_exp proc_desc tenv loc e
load_type summary tenv loc typ' astate |> add_loads_of_exp summary tenv loc e
| Var _ | Const _ | Closure _ | Sizeof _ | Lindex _ | Lvar _ ->
astate
let exec_call pdesc tenv callee args loc astate =
let exec_call summary tenv callee args loc astate =
match args with
| [_; (Exp.Sizeof {typ}, _)] when Typ.Procname.equal callee BuiltinDecl.__instanceof ->
(* this matches downcasts/instanceof and exception handlers *)
load_type pdesc tenv loc typ astate
load_type summary tenv loc typ astate
| _ ->
(* invokeinterface / invokespecial / invokestatic / invokevirtual / new *)
List.fold args ~init:astate ~f:(fun acc (exp, _) -> add_loads_of_exp pdesc tenv loc exp acc)
|> do_call pdesc callee loc
List.fold args ~init:astate ~f:(fun acc (exp, _) -> add_loads_of_exp summary tenv loc exp acc)
|> do_call summary callee loc
let exec_instr pdesc tenv astate _ (instr : Sil.instr) =
let exec_instr summary tenv astate _ (instr : Sil.instr) =
match instr with
| Call (_, Const (Cfun callee), args, loc, _) ->
exec_call pdesc tenv callee args loc astate
exec_call summary tenv callee args loc astate
| Load (_, exp, _, loc) | Prune (exp, loc, _, _) ->
(* NB the java frontend seems to always translate complex guards into a sequence of
instructions plus a prune on logical vars only. So the below is only for completeness. *)
add_loads_of_exp pdesc tenv loc exp astate
add_loads_of_exp summary tenv loc exp astate
| Store (e1, _, e2, loc) ->
add_loads_of_exp pdesc tenv loc e1 astate |> add_loads_of_exp pdesc tenv loc e2
add_loads_of_exp summary tenv loc e1 astate |> add_loads_of_exp summary tenv loc e2
| _ ->
astate
let report_loads proc_desc summary astate =
let report_loads summary astate =
let report_load ({ClassLoadsDomain.Event.loc; elem} as event) =
if String.is_prefix ~prefix:"java." elem then ()
else
@ -116,7 +117,7 @@ let report_loads proc_desc summary astate =
let msg = Format.asprintf "Class %s loaded" elem in
Reporting.log_warning summary ~loc ~ltr IssueType.class_load msg
in
let pname = Procdesc.get_proc_name proc_desc in
let pname = Summary.get_proc_name summary in
Typ.Procname.get_class_name pname
|> Option.iter ~f:(fun clazz ->
let method_strname = Typ.Procname.get_method pname in
@ -133,10 +134,10 @@ let analyze_procedure {Callbacks.tenv; summary} =
(* load the method's class *)
let init =
Typ.Procname.get_class_type_name proc_name
|> Option.fold ~init:ClassLoadsDomain.bottom ~f:(load_class proc_desc tenv loc)
|> Option.fold ~init:ClassLoadsDomain.bottom ~f:(load_class summary tenv loc)
in
let post = Procdesc.fold_instrs proc_desc ~init ~f:(exec_instr proc_desc tenv) in
report_loads proc_desc summary post ;
let post = Procdesc.fold_instrs proc_desc ~init ~f:(exec_instr summary tenv) in
report_loads summary post ;
let result = Payload.update_summary post summary in
L.debug Analysis Verbose "CL: FINISHED ANALYZING %a@." Typ.Procname.pp proc_name ;
result

@ -197,7 +197,8 @@ let should_report pdesc =
true
let report_errors pdesc astate summary =
let report_errors astate summary =
let pdesc = Summary.get_proc_desc summary in
let proc_name = Procdesc.get_proc_name pdesc in
match astate with
| Some astate ->
@ -224,13 +225,12 @@ let compute_summary summary tenv get_callee_summary inferbo_invariant_map =
let checker {Callbacks.tenv; summary; integer_type_widths} : Summary.t =
let proc_desc = Summary.get_proc_desc summary in
let inferbo_invariant_map =
BufferOverrunAnalysis.cached_compute_invariant_map summary tenv integer_type_widths
in
let get_callee_summary = Payload.read proc_desc in
let get_callee_summary callee_pname = Payload.read ~caller_summary:summary ~callee_pname in
let astate = compute_summary summary tenv get_callee_summary inferbo_invariant_map in
report_errors proc_desc astate summary ;
report_errors astate summary ;
match astate with
| Some astate ->
debug "Purity summary :%a \n" PurityDomain.pp astate ;

@ -99,14 +99,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
|| is_array_element_passed_by_ref callee_formals t access_expr idx
let report_on_function_params pdesc tenv maybe_uninit_vars actuals loc summary callee_formals_opt
=
let report_on_function_params tenv maybe_uninit_vars actuals loc summary callee_formals_opt =
List.iteri actuals ~f:(fun idx e ->
match HilExp.ignore_cast e with
| HilExp.AccessExpression access_expr ->
let _, t = HilExp.AccessExpression.get_base access_expr in
if
should_report_var pdesc tenv maybe_uninit_vars access_expr
should_report_var (Summary.get_proc_desc summary) tenv maybe_uninit_vars access_expr
&& (not (Typ.is_pointer t))
&& not
(Option.exists callee_formals_opt ~f:(fun callee_formals ->
@ -153,8 +152,8 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
else None
let remove_initialized_params pdesc call maybe_uninit_vars idx access_expr remove_fields =
match Payload.read pdesc call with
let remove_initialized_params summary call maybe_uninit_vars idx access_expr remove_fields =
match Payload.read ~caller_summary:summary ~callee_pname:call with
| Some {pre= init_formals; post= _} -> (
match init_nth_actual_param call idx init_formals with
| Some var_formal ->
@ -171,8 +170,8 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
(* true if a function initializes at least a param or a field of a struct param *)
let function_initializes_some_formal_params pdesc call =
match Payload.read pdesc call with
let function_initializes_some_formal_params summary call =
match Payload.read ~caller_summary:summary ~callee_pname:call with
| Some {pre= initialized_formal_params; post= _} ->
not (D.is_empty initialized_formal_params)
| _ ->
@ -234,7 +233,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
(* if it's a default constructor, we use the following heuristic: we assume that it initializes
correctly all fields when there is an implementation of the constructor that initilizes at least one
field. If there is no explicit implementation we cannot assume fields are initialized *)
if function_initializes_some_formal_params pdesc call then
if function_initializes_some_formal_params summary call then
let maybe_uninit_vars =
(* in HIL/SIL the default constructor has only one param: the struct *)
MaybeUninitVars.remove_all_fields tenv base astate.maybe_uninit_vars
@ -269,7 +268,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
~f:(is_fld_or_array_elem_passed_by_ref t access_expr idx) -> (
match pname_opt with
| Some pname when Config.uninit_interproc ->
remove_initialized_params pdesc pname acc idx access_expr_to_remove false
remove_initialized_params summary pname acc idx access_expr_to_remove false
| _ ->
MaybeUninitVars.remove access_expr_to_remove acc )
| base when Option.exists pname_opt ~f:Typ.Procname.is_constructor ->
@ -278,7 +277,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| _, {Typ.desc= Tptr _} -> (
match pname_opt with
| Some pname when Config.uninit_interproc ->
remove_initialized_params pdesc pname acc idx access_expr_to_remove true
remove_initialized_params summary pname acc idx access_expr_to_remove true
| _ ->
MaybeUninitVars.remove_everything_under tenv access_expr_to_remove acc )
| _ ->
@ -292,8 +291,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
in
( match call with
| Direct _ ->
report_on_function_params pdesc tenv maybe_uninit_vars actuals loc summary
callee_formals_opt
report_on_function_params tenv maybe_uninit_vars actuals loc summary callee_formals_opt
| Indirect _ ->
() ) ;
{astate with maybe_uninit_vars}

@ -322,7 +322,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
astate
| NoEffect -> (
let rebased_summary_opt =
Payload.read pdesc callee_pname
Payload.read ~caller_summary:summary ~callee_pname
|> Option.map ~f:(fun summary ->
let rebased_accesses =
Ondemand.get_proc_desc callee_pname
@ -1170,15 +1170,16 @@ let make_results_table file_env =
(fun snapshot acc -> ReportMap.add {threads; snapshot; tenv; procdesc} acc)
accesses acc
in
List.fold file_env ~init:ReportMap.empty ~f:(fun acc (tenv, proc_desc) ->
Procdesc.get_proc_name proc_desc |> Payload.read proc_desc
|> Option.fold ~init:acc ~f:(aggregate_post tenv proc_desc) )
List.fold file_env ~init:ReportMap.empty ~f:(fun acc (tenv, summary) ->
Payload.read_toplevel_procedure (Summary.get_proc_name summary)
|> Option.fold ~init:acc ~f:(aggregate_post tenv (Summary.get_proc_desc summary)) )
(* aggregate all of the procedures in the file env by their declaring
class. this lets us analyze each class individually *)
let aggregate_by_class file_env =
List.fold file_env ~init:String.Map.empty ~f:(fun acc ((tenv, pdesc) as proc) ->
List.fold file_env ~init:String.Map.empty ~f:(fun acc ((tenv, summary) as proc) ->
let pdesc = Summary.get_proc_desc summary in
if should_report_on_proc tenv pdesc then
Procdesc.get_proc_name pdesc |> Typ.Procname.get_class_name
|> Option.fold ~init:acc ~f:(fun acc classname ->

@ -81,7 +81,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
in
let do_unlock locks astate = List.filter_map ~f:get_lock_path locks |> Domain.release astate in
let do_call callee loc astate =
Payload.read (Summary.get_proc_desc summary) callee
Payload.read ~caller_summary:summary ~callee_pname:callee
|> Option.value_map ~default:astate ~f:(Domain.integrate_summary tenv astate callee loc)
in
match instr with
@ -327,7 +327,7 @@ let should_report pdesc =
false
let fold_reportable_summaries (tenv, current_pdesc) clazz ~init ~f =
let fold_reportable_summaries (tenv, current_summary) clazz ~init ~f =
let methods =
Tenv.lookup tenv clazz
|> Option.value_map ~default:[] ~f:(fun tstruct -> tstruct.Typ.Struct.methods)
@ -336,7 +336,7 @@ let fold_reportable_summaries (tenv, current_pdesc) clazz ~init ~f =
Ondemand.get_proc_desc mthd
|> Option.value_map ~default:acc ~f:(fun other_pdesc ->
if should_report other_pdesc then
Payload.read current_pdesc mthd
Payload.read ~caller_summary:current_summary ~callee_pname:mthd
|> Option.map ~f:(fun payload -> (mthd, payload))
|> Option.fold ~init:acc ~f
else acc )
@ -353,8 +353,8 @@ let fold_reportable_summaries (tenv, current_pdesc) clazz ~init ~f =
once, as opposed to twice with all other deadlock pairs. *)
let report_deadlocks env {StarvationDomain.order; ui} report_map' =
let open StarvationDomain in
let _, current_pdesc = env in
let current_pname = Procdesc.get_proc_name current_pdesc in
let _, current_summary = env in
let current_pname = Summary.get_proc_name current_summary in
let report_endpoint_elem current_elem endpoint_pname elem report_map =
if
not
@ -409,8 +409,8 @@ let report_deadlocks env {StarvationDomain.order; ui} report_map' =
let report_starvation env {StarvationDomain.events; ui} report_map' =
let open StarvationDomain in
let _, current_pdesc = env in
let current_pname = Procdesc.get_proc_name current_pdesc in
let _, current_summary = env in
let current_pname = Summary.get_proc_name current_summary in
let report_remote_block ui_explain event current_lock endpoint_pname endpoint_elem report_map =
let lock = endpoint_elem.Order.elem.first in
match endpoint_elem.Order.elem.eventually.elem with
@ -489,9 +489,10 @@ let report_starvation env {StarvationDomain.events; ui} report_map' =
let reporting {Callbacks.procedures; source_file} =
let report_procedure issue_log ((tenv, proc_desc) as env) =
let report_procedure issue_log ((tenv, summary) as env) =
let proc_desc = Summary.get_proc_desc summary in
if should_report proc_desc then
Payload.read proc_desc (Procdesc.get_proc_name proc_desc)
Payload.read_toplevel_procedure (Procdesc.get_proc_name proc_desc)
|> Option.value_map ~default:issue_log ~f:(fun summary ->
report_deadlocks env summary ReportMap.empty
|> report_starvation env summary

@ -305,7 +305,7 @@ let remove_vars vars astate =
let call ~caller_summary call_loc callee_pname ~ret ~actuals astate =
match PulsePayload.read_full caller_summary.Summary.proc_desc callee_pname with
match PulsePayload.read_full ~caller_summary ~callee_pname with
| Some (callee_proc_desc, preposts) ->
let formals =
Procdesc.get_formals callee_proc_desc

@ -128,7 +128,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
(* read_summary will trigger ondemand analysis of the current proc. we don't want that. *)
TaintDomain.bottom
else
match Payload.read (Summary.get_proc_desc proc_data.summary) pname with
match Payload.read ~caller_summary:proc_data.summary ~callee_pname:pname with
| Some summary ->
TaintSpecification.of_summary_access_tree summary
| None ->
@ -655,7 +655,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
add_actual_source source index actuals astate_with_sink proc_data )
in
let astate_with_summary =
match Payload.read (Summary.get_proc_desc proc_data.summary) callee_pname with
match Payload.read ~caller_summary:proc_data.summary ~callee_pname with
| None ->
handle_unknown_call callee_pname astate_with_direct_sources
| Some summary -> (

Loading…
Cancel
Save