[backend] Pass the execution environment around to use it to load tenv of callees in a more efficient way

Reviewed By: jvillard

Differential Revision: D7350922

fbshipit-source-id: 58e0dca
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent d746b10bf3
commit 9c9519fddb

@ -18,12 +18,12 @@ module F = Format
type t = Builtin.registered type t = Builtin.registered
(** model va_arg as always returning 0 *) (** model va_arg as always returning 0 *)
let execute___builtin_va_arg {Builtin.pdesc; tenv; prop_; path; ret_id; args; loc} let execute___builtin_va_arg {Builtin.pdesc; tenv; prop_; path; ret_id; args; loc; exe_env}
: Builtin.ret_typ = : Builtin.ret_typ =
match (args, ret_id) with match (args, ret_id) with
| [_; _; (lexp3, typ3)], _ -> | [_; _; (lexp3, typ3)], _ ->
let instr' = Sil.Store (lexp3, typ3, Exp.zero, loc) in let instr' = Sil.Store (lexp3, typ3, Exp.zero, loc) in
SymExec.instrs ~mask_errors:true tenv pdesc [instr'] [(prop_, path)] SymExec.instrs ~mask_errors:true exe_env tenv pdesc [instr'] [(prop_, path)]
| _ -> | _ ->
raise (Exceptions.Wrong_argument_number __POS__) raise (Exceptions.Wrong_argument_number __POS__)
@ -615,7 +615,7 @@ let execute_alloc mk can_return_null {Builtin.pdesc; tenv; prop_; path; ret_id;
else [(prop_alloc, path)] else [(prop_alloc, path)]
let execute___cxx_typeid ({Builtin.pdesc; tenv; prop_; args; loc} as r) : Builtin.ret_typ = let execute___cxx_typeid ({Builtin.pdesc; tenv; prop_; args; loc; exe_env} as r) : Builtin.ret_typ =
match args with match args with
| type_info_exp :: rest | type_info_exp :: rest
-> ( -> (
@ -636,14 +636,15 @@ let execute___cxx_typeid ({Builtin.pdesc; tenv; prop_; args; loc} as r) : Builti
let set_instr = let set_instr =
Sil.Store (field_exp, Typ.mk Tvoid, Exp.Const (Const.Cstr typ_string), loc) Sil.Store (field_exp, Typ.mk Tvoid, Exp.Const (Const.Cstr typ_string), loc)
in in
SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] res SymExec.instrs ~mask_errors:true exe_env tenv pdesc [set_instr] res
| _ -> | _ ->
res ) res )
| _ -> | _ ->
raise (Exceptions.Wrong_argument_number __POS__) raise (Exceptions.Wrong_argument_number __POS__)
let execute_pthread_create ({Builtin.tenv; prop_; path; args} as builtin_args) : Builtin.ret_typ = let execute_pthread_create ({Builtin.tenv; prop_; path; args; exe_env} as builtin_args)
: Builtin.ret_typ =
match args with match args with
| [_; _; start_routine; arg] | [_; _; start_routine; arg]
-> ( -> (
@ -659,7 +660,8 @@ let execute_pthread_create ({Builtin.tenv; prop_; path; args} as builtin_args) :
| None -> | None ->
assert false assert false
| Some callee_summary -> | Some callee_summary ->
SymExec.proc_call callee_summary {builtin_args with args= [(routine_arg, snd arg)]} ) SymExec.proc_call exe_env callee_summary
{builtin_args with args= [(routine_arg, snd arg)]} )
| _ -> | _ ->
L.d_str "pthread_create: unknown function " ; L.d_str "pthread_create: unknown function " ;
Sil.d_exp routine_name ; Sil.d_exp routine_name ;
@ -747,7 +749,7 @@ let execute___infer_assume {Builtin.tenv; prop_; path; args} : Builtin.ret_typ =
(* creates a named error state *) (* creates a named error state *)
let execute___infer_fail {Builtin.pdesc; tenv; prop_; path; args; loc} : Builtin.ret_typ = let execute___infer_fail {Builtin.pdesc; tenv; prop_; path; args; loc; exe_env} : Builtin.ret_typ =
let error_str = let error_str =
match args with match args with
| [(lexp_msg, _)] -> ( | [(lexp_msg, _)] -> (
@ -762,11 +764,11 @@ let execute___infer_fail {Builtin.pdesc; tenv; prop_; path; args; loc} : Builtin
let set_instr = let set_instr =
Sil.Store (Exp.Lvar Sil.custom_error, Typ.mk Tvoid, Exp.Const (Const.Cstr error_str), loc) Sil.Store (Exp.Lvar Sil.custom_error, Typ.mk Tvoid, Exp.Const (Const.Cstr error_str), loc)
in in
SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] [(prop_, path)] SymExec.instrs ~mask_errors:true exe_env tenv pdesc [set_instr] [(prop_, path)]
(* translate builtin assertion failure *) (* translate builtin assertion failure *)
let execute___assert_fail {Builtin.pdesc; tenv; prop_; path; args; loc} : Builtin.ret_typ = let execute___assert_fail {Builtin.pdesc; tenv; prop_; path; args; loc; exe_env} : Builtin.ret_typ =
let error_str = let error_str =
match List.length args with match List.length args with
| 4 -> | 4 ->
@ -777,10 +779,11 @@ let execute___assert_fail {Builtin.pdesc; tenv; prop_; path; args; loc} : Builti
let set_instr = let set_instr =
Sil.Store (Exp.Lvar Sil.custom_error, Typ.mk Tvoid, Exp.Const (Const.Cstr error_str), loc) Sil.Store (Exp.Lvar Sil.custom_error, Typ.mk Tvoid, Exp.Const (Const.Cstr error_str), loc)
in in
SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] [(prop_, path)] SymExec.instrs ~mask_errors:true exe_env tenv pdesc [set_instr] [(prop_, path)]
let execute_objc_alloc_no_fail symb_state typ alloc_fun_opt {Builtin.pdesc; tenv; ret_id; loc} = let execute_objc_alloc_no_fail symb_state typ alloc_fun_opt
{Builtin.pdesc; tenv; ret_id; loc; exe_env} =
let alloc_fun = Exp.Const (Const.Cfun BuiltinDecl.__objc_alloc_no_fail) in let alloc_fun = Exp.Const (Const.Cfun BuiltinDecl.__objc_alloc_no_fail) in
let ptr_typ = Typ.mk (Tptr (typ, Typ.Pk_pointer)) in let ptr_typ = Typ.mk (Tptr (typ, Typ.Pk_pointer)) in
let sizeof_typ = Exp.Sizeof {typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact} in let sizeof_typ = Exp.Sizeof {typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact} in
@ -794,7 +797,7 @@ let execute_objc_alloc_no_fail symb_state typ alloc_fun_opt {Builtin.pdesc; tenv
let alloc_instr = let alloc_instr =
Sil.Call (ret_id, alloc_fun, [(sizeof_typ, ptr_typ)] @ alloc_fun_exp, loc, CallFlags.default) Sil.Call (ret_id, alloc_fun, [(sizeof_typ, ptr_typ)] @ alloc_fun_exp, loc, CallFlags.default)
in in
SymExec.instrs tenv pdesc [alloc_instr] symb_state SymExec.instrs exe_env tenv pdesc [alloc_instr] symb_state
(* NSArray models *) (* NSArray models *)

@ -21,7 +21,8 @@ type args =
; ret_id: (Ident.t * Typ.t) option ; ret_id: (Ident.t * Typ.t) option
; args: (Exp.t * Typ.t) list ; args: (Exp.t * Typ.t) list
; proc_name: Typ.Procname.t ; proc_name: Typ.Procname.t
; loc: Location.t } ; loc: Location.t
; exe_env: Exe_env.t }
type ret_typ = (Prop.normal Prop.t * Paths.Path.t) list type ret_typ = (Prop.normal Prop.t * Paths.Path.t) list

@ -20,7 +20,8 @@ type args =
; ret_id: (Ident.t * Typ.t) option ; ret_id: (Ident.t * Typ.t) option
; args: (Exp.t * Typ.t) list ; args: (Exp.t * Typ.t) list
; proc_name: Typ.Procname.t ; proc_name: Typ.Procname.t
; loc: Location.t } ; loc: Location.t
; exe_env: Exe_env.t }
type ret_typ = (Prop.normal Prop.t * Paths.Path.t) list type ret_typ = (Prop.normal Prop.t * Paths.Path.t) list

@ -19,7 +19,8 @@ type proc_callback_args =
; get_procs_in_file: Typ.Procname.t -> Typ.Procname.t list ; get_procs_in_file: Typ.Procname.t -> Typ.Procname.t list
; tenv: Tenv.t ; tenv: Tenv.t
; summary: Specs.summary ; summary: Specs.summary
; proc_desc: Procdesc.t } ; proc_desc: Procdesc.t
; exe_env: Exe_env.t }
type proc_callback_t = proc_callback_args -> Specs.summary type proc_callback_t = proc_callback_args -> Specs.summary
@ -67,7 +68,7 @@ let iterate_procedure_callbacks get_proc_desc exe_env summary proc_desc =
List.fold ~init:summary List.fold ~init:summary
~f:(fun summary (language, resolved, proc_callback) -> ~f:(fun summary (language, resolved, proc_callback) ->
if Language.equal language procedure_language && (resolved || not is_specialized) then if Language.equal language procedure_language && (resolved || not is_specialized) then
proc_callback {get_proc_desc; get_procs_in_file; tenv; summary; proc_desc} proc_callback {get_proc_desc; get_procs_in_file; tenv; summary; proc_desc; exe_env}
else summary ) else summary )
!procedure_callbacks !procedure_callbacks

@ -16,7 +16,8 @@ type proc_callback_args =
; get_procs_in_file: Typ.Procname.t -> Typ.Procname.t list ; get_procs_in_file: Typ.Procname.t -> Typ.Procname.t list
; tenv: Tenv.t ; tenv: Tenv.t
; summary: Specs.summary ; summary: Specs.summary
; proc_desc: Procdesc.t } ; proc_desc: Procdesc.t
; exe_env: Exe_env.t }
(** Type of a procedure callback: (** Type of a procedure callback:
- List of all the procedures the callback will be called on. - List of all the procedures the callback will be called on.

@ -375,14 +375,15 @@ let instrs_get_normal_vars instrs =
(** Perform symbolic execution for a node starting from an initial prop *) (** Perform symbolic execution for a node starting from an initial prop *)
let do_symbolic_execution proc_cfg handle_exn tenv (node: ProcCfg.Exceptional.node) let do_symbolic_execution exe_env proc_cfg handle_exn tenv (node: ProcCfg.Exceptional.node)
(prop: Prop.normal Prop.t) (path: Paths.Path.t) = (prop: Prop.normal Prop.t) (path: Paths.Path.t) =
State.mark_execution_start node ; State.mark_execution_start node ;
let instrs = ProcCfg.Exceptional.instrs node in let instrs = ProcCfg.Exceptional.instrs node in
(* fresh normal vars must be fresh w.r.t. instructions *) (* fresh normal vars must be fresh w.r.t. instructions *)
Ident.update_name_generator (instrs_get_normal_vars instrs) ; Ident.update_name_generator (instrs_get_normal_vars instrs) ;
let pset = let pset =
SymExec.node handle_exn tenv proc_cfg node (Paths.PathSet.from_renamed_list [(prop, path)]) SymExec.node handle_exn exe_env tenv proc_cfg node
(Paths.PathSet.from_renamed_list [(prop, path)])
in in
L.d_strln ".... After Symbolic Execution ...." ; L.d_strln ".... After Symbolic Execution ...." ;
Propset.d prop (Paths.PathSet.to_propset tenv pset) ; Propset.d prop (Paths.PathSet.to_propset tenv pset) ;
@ -400,7 +401,7 @@ let mark_visited summary node =
else stats.Specs.nodes_visited_re <- IntSet.add (node_id :> int) stats.Specs.nodes_visited_re else stats.Specs.nodes_visited_re <- IntSet.add (node_id :> int) stats.Specs.nodes_visited_re
let forward_tabulate tenv proc_cfg wl = let forward_tabulate exe_env tenv proc_cfg wl =
let pname = Procdesc.get_proc_name (ProcCfg.Exceptional.proc_desc proc_cfg) in let pname = Procdesc.get_proc_name (ProcCfg.Exceptional.proc_desc proc_cfg) in
let handle_exn_node curr_node exn = let handle_exn_node curr_node exn =
Exceptions.print_exception_html "Failure of symbolic execution: " exn ; Exceptions.print_exception_html "Failure of symbolic execution: " exn ;
@ -456,7 +457,7 @@ let forward_tabulate tenv proc_cfg wl =
L.d_increase_indent 1 ; L.d_increase_indent 1 ;
try try
State.reset_diverging_states_node () ; State.reset_diverging_states_node () ;
let pset = do_symbolic_execution proc_cfg handle_exn tenv curr_node prop path in let pset = do_symbolic_execution exe_env proc_cfg handle_exn tenv curr_node prop path in
let normal_succ_nodes = ProcCfg.Exceptional.normal_succs proc_cfg curr_node in let normal_succ_nodes = ProcCfg.Exceptional.normal_succs proc_cfg curr_node in
let exn_succ_nodes = ProcCfg.Exceptional.exceptional_succs proc_cfg curr_node in let exn_succ_nodes = ProcCfg.Exceptional.exceptional_succs proc_cfg curr_node in
propagate_nodes_divergence tenv proc_cfg pset normal_succ_nodes exn_succ_nodes wl ; propagate_nodes_divergence tenv proc_cfg pset normal_succ_nodes exn_succ_nodes wl ;
@ -746,8 +747,8 @@ let initial_prop_from_pre tenv curr_f pre =
(** Re-execute one precondition and return some spec if there was no re-execution error. *) (** Re-execute one precondition and return some spec if there was no re-execution error. *)
let execute_filter_prop wl tenv proc_cfg init_node (precondition: Prop.normal Specs.Jprop.t) let execute_filter_prop exe_env wl tenv proc_cfg init_node
: Prop.normal Specs.spec option = (precondition: Prop.normal Specs.Jprop.t) : Prop.normal Specs.spec option =
let pdesc = ProcCfg.Exceptional.proc_desc proc_cfg in let pdesc = ProcCfg.Exceptional.proc_desc proc_cfg in
let pname = Procdesc.get_proc_name pdesc in let pname = Procdesc.get_proc_name pdesc in
do_before_node 0 init_node ; do_before_node 0 init_node ;
@ -765,7 +766,7 @@ let execute_filter_prop wl tenv proc_cfg init_node (precondition: Prop.normal Sp
try try
Worklist.add wl init_node ; Worklist.add wl init_node ;
ignore (path_set_put_todo wl init_node init_edgeset) ; ignore (path_set_put_todo wl init_node init_edgeset) ;
forward_tabulate tenv proc_cfg wl ; forward_tabulate exe_env tenv proc_cfg wl ;
do_before_node 0 init_node ; do_before_node 0 init_node ;
L.d_strln_color Green L.d_strln_color Green
("#### Finished: RE-execution for " ^ Typ.Procname.to_string pname ^ " ####") ; ("#### Finished: RE-execution for " ^ Typ.Procname.to_string pname ^ " ####") ;
@ -812,7 +813,7 @@ type exe_phase = (unit -> unit) * (unit -> Prop.normal Specs.spec list * Specs.p
and [get_results ()] returns the results computed. and [get_results ()] returns the results computed.
This function is architected so that [get_results ()] can be called even after This function is architected so that [get_results ()] can be called even after
[go ()] was interrupted by and exception. *) [go ()] was interrupted by and exception. *)
let perform_analysis_phase tenv (summary: Specs.summary) (proc_cfg: ProcCfg.Exceptional.t) let perform_analysis_phase exe_env tenv (summary: Specs.summary) (proc_cfg: ProcCfg.Exceptional.t)
: exe_phase = : exe_phase =
let pname = Specs.get_proc_name summary in let pname = Specs.get_proc_name summary in
let start_node = ProcCfg.Exceptional.start_node proc_cfg in let start_node = ProcCfg.Exceptional.start_node proc_cfg in
@ -844,7 +845,7 @@ let perform_analysis_phase tenv (summary: Specs.summary) (proc_cfg: ProcCfg.Exce
L.d_decrease_indent 1 ; L.d_decrease_indent 1 ;
Worklist.add wl start_node ; Worklist.add wl start_node ;
ignore (path_set_put_todo wl start_node init_edgeset) ; ignore (path_set_put_todo wl start_node init_edgeset) ;
forward_tabulate tenv proc_cfg wl forward_tabulate exe_env tenv proc_cfg wl
in in
let get_results (wl: Worklist.t) () = let get_results (wl: Worklist.t) () =
State.process_execution_failures Reporting.log_warning_deprecated pname ; State.process_execution_failures Reporting.log_warning_deprecated pname ;
@ -872,7 +873,7 @@ let perform_analysis_phase tenv (summary: Specs.summary) (proc_cfg: ProcCfg.Exce
let go () = let go () =
let filter p = let filter p =
let wl = path_set_create_worklist proc_cfg in let wl = path_set_create_worklist proc_cfg in
let speco = execute_filter_prop wl tenv proc_cfg start_node p in let speco = execute_filter_prop exe_env wl tenv proc_cfg start_node p in
(match speco with None -> () | Some spec -> valid_specs := !valid_specs @ [spec]) ; (match speco with None -> () | Some spec -> valid_specs := !valid_specs @ [spec]) ;
speco speco
in in
@ -1112,12 +1113,12 @@ let update_summary tenv prev_summary specs phase res =
(** Analyze the procedure and return the resulting summary. *) (** Analyze the procedure and return the resulting summary. *)
let analyze_proc tenv proc_cfg : Specs.summary = let analyze_proc exe_env tenv proc_cfg : Specs.summary =
let proc_desc = ProcCfg.Exceptional.proc_desc proc_cfg in let proc_desc = ProcCfg.Exceptional.proc_desc proc_cfg in
let proc_name = Procdesc.get_proc_name proc_desc in let proc_name = Procdesc.get_proc_name proc_desc in
reset_global_values proc_desc ; reset_global_values proc_desc ;
let summary = Specs.get_summary_unsafe "analyze_proc" proc_name in let summary = Specs.get_summary_unsafe "analyze_proc" proc_name in
let go, get_results = perform_analysis_phase tenv summary proc_cfg in let go, get_results = perform_analysis_phase exe_env tenv summary proc_cfg in
let res = Timeout.exe_timeout go () in let res = Timeout.exe_timeout go () in
let specs, phase = get_results () in let specs, phase = get_results () in
let updated_summary = update_summary tenv summary specs phase res in let updated_summary = update_summary tenv summary specs phase res in
@ -1185,22 +1186,22 @@ let perform_transition proc_cfg tenv proc_name =
() ()
let analyze_procedure_aux tenv proc_desc = let analyze_procedure_aux exe_env tenv proc_desc =
let proc_name = Procdesc.get_proc_name proc_desc in let proc_name = Procdesc.get_proc_name proc_desc in
let proc_cfg = ProcCfg.Exceptional.from_pdesc proc_desc in let proc_cfg = ProcCfg.Exceptional.from_pdesc proc_desc in
Preanal.do_preanalysis proc_desc tenv ; Preanal.do_preanalysis proc_desc tenv ;
let summaryfp = Config.run_in_footprint_mode (analyze_proc tenv) proc_cfg in let summaryfp = Config.run_in_footprint_mode (analyze_proc exe_env tenv) proc_cfg in
Specs.add_summary proc_name summaryfp ; Specs.add_summary proc_name summaryfp ;
perform_transition proc_cfg tenv proc_name ; perform_transition proc_cfg tenv proc_name ;
let summaryre = Config.run_in_re_execution_mode (analyze_proc tenv) proc_cfg in let summaryre = Config.run_in_re_execution_mode (analyze_proc exe_env tenv) proc_cfg in
Specs.add_summary proc_name summaryre ; Specs.add_summary proc_name summaryre ;
summaryre summaryre
let analyze_procedure {Callbacks.summary; proc_desc; tenv} : Specs.summary = let analyze_procedure {Callbacks.summary; proc_desc; tenv; exe_env} : Specs.summary =
let proc_name = Procdesc.get_proc_name proc_desc in let proc_name = Procdesc.get_proc_name proc_desc in
Specs.add_summary proc_name summary ; Specs.add_summary proc_name summary ;
( try ignore (analyze_procedure_aux tenv proc_desc) with exn -> ( try ignore (analyze_procedure_aux exe_env tenv proc_desc) with exn ->
reraise_if exn ~f:(fun () -> not (Exceptions.handle_exception exn)) ; reraise_if exn ~f:(fun () -> not (Exceptions.handle_exception exn)) ;
Reporting.log_error_deprecated proc_name exn ) ; Reporting.log_error_deprecated proc_name exn ) ;
Specs.get_summary_unsafe __FILE__ proc_name Specs.get_summary_unsafe __FILE__ proc_name

@ -1041,7 +1041,7 @@ let execute_store ?(report_deref_errors= true) pname pdesc tenv lhs_exp typ rhs_
(** Execute [instr] with a symbolic heap [prop].*) (** Execute [instr] with a symbolic heap [prop].*)
let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path let rec sym_exec exe_env tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
: (Prop.normal Prop.t * Paths.Path.t) list = : (Prop.normal Prop.t * Paths.Path.t) list =
let current_pname = Procdesc.get_proc_name current_pdesc in let current_pname = Procdesc.get_proc_name current_pdesc in
State.set_instr instr_ ; State.set_instr instr_ ;
@ -1096,7 +1096,8 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
; ret_id ; ret_id
; args= actual_args ; args= actual_args
; proc_name= callee_pname ; proc_name= callee_pname
; loc } ; loc
; exe_env }
in in
if is_objc_instance_method then if is_objc_instance_method then
handle_objc_instance_method_call_or_skip current_pdesc tenv actual_args path callee_pname handle_objc_instance_method_call_or_skip current_pdesc tenv actual_args path callee_pname
@ -1104,7 +1105,7 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
else skip_res () else skip_res ()
in in
let call_args prop_ proc_name args ret_id loc = let call_args prop_ proc_name args ret_id loc =
{Builtin.pdesc= current_pdesc; instr; tenv; prop_; path; ret_id; args; proc_name; loc} {Builtin.pdesc= current_pdesc; instr; tenv; prop_; path; ret_id; args; proc_name; loc; exe_env}
in in
match instr with match instr with
| Sil.Load (id, rhs_exp, typ, loc) -> | Sil.Load (id, rhs_exp, typ, loc) ->
@ -1173,7 +1174,8 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
| Some resolved_summary -> | Some resolved_summary ->
match reason_to_skip resolved_summary with match reason_to_skip resolved_summary with
| None -> | None ->
proc_call resolved_summary (call_args prop_ callee_pname norm_args ret_id loc) proc_call exe_env resolved_summary
(call_args prop_ callee_pname norm_args ret_id loc)
| Some reason -> | Some reason ->
let proc_attrs = Specs.get_attributes resolved_summary in let proc_attrs = Specs.get_attributes resolved_summary in
let ret_annots, _ = proc_attrs.ProcAttributes.method_annotation in let ret_annots, _ = proc_attrs.ProcAttributes.method_annotation in
@ -1199,7 +1201,7 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
match reason_to_skip callee_summary with match reason_to_skip callee_summary with
| None -> | None ->
let handled_args = call_args norm_prop pname url_handled_args ret_id loc in let handled_args = call_args norm_prop pname url_handled_args ret_id loc in
proc_call callee_summary handled_args proc_call exe_env callee_summary handled_args
| Some reason -> | Some reason ->
let proc_attrs = Specs.get_attributes callee_summary in let proc_attrs = Specs.get_attributes callee_summary in
let ret_annots, _ = proc_attrs.ProcAttributes.method_annotation in let ret_annots, _ = proc_attrs.ProcAttributes.method_annotation in
@ -1229,7 +1231,7 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
normalize_params tenv current_pname prop_r extended_actual_params normalize_params tenv current_pname prop_r extended_actual_params
in in
Logging.d_strln "Calling method specialized with blocks... " ; Logging.d_strln "Calling method specialized with blocks... " ;
proc_call resolved_summary proc_call exe_env resolved_summary
(call_args prop_r resolved_pname n_extended_actual_params ret_id loc) (call_args prop_r resolved_pname n_extended_actual_params ret_id loc)
| None -> | None ->
(* Generic fun call with known name *) (* Generic fun call with known name *)
@ -1273,8 +1275,8 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
(sym_exec_objc_accessor objc_accessor ret_type) (sym_exec_objc_accessor objc_accessor ret_type)
| None, true -> | None, true ->
(* If it's an alloc model, call alloc rather than skipping *) (* If it's an alloc model, call alloc rather than skipping *)
sym_exec_alloc_model callee_pname ret_type tenv ret_id current_pdesc loc sym_exec_alloc_model exe_env callee_pname ret_type tenv ret_id
prop path current_pdesc loc prop path
| None, false -> | None, false ->
let is_objc_instance_method = let is_objc_instance_method =
ProcAttributes.equal_clang_method_kind ProcAttributes.equal_clang_method_kind
@ -1287,7 +1289,7 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
skip_call ~reason:"function or method not found" prop path resolved_pname skip_call ~reason:"function or method not found" prop path resolved_pname
ret_annots loc ret_id ret_typ_opt n_actual_params ret_annots loc ret_id ret_typ_opt n_actual_params
else else
proc_call proc_call exe_env
(Option.value_exn resolved_summary_opt) (Option.value_exn resolved_summary_opt)
(call_args prop resolved_pname n_actual_params ret_id loc) (call_args prop resolved_pname n_actual_params ret_id loc)
in in
@ -1320,7 +1322,8 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
; ret_id ; ret_id
; args= n_actual_params ; args= n_actual_params
; proc_name= callee_pname ; proc_name= callee_pname
; loc } ) ; loc
; exe_env } )
| Sil.Nullify (pvar, _) | Sil.Nullify (pvar, _)
-> ( -> (
let eprop = Prop.expose prop_ in let eprop = Prop.expose prop_ in
@ -1377,12 +1380,12 @@ and diverge prop path =
(** Symbolic execution of a sequence of instructions. (** Symbolic execution of a sequence of instructions.
If errors occur and [mask_errors] is true, just treat as skip. *) If errors occur and [mask_errors] is true, just treat as skip. *)
and instrs ?(mask_errors= false) tenv pdesc instrs ppl = and instrs ?(mask_errors= false) exe_env tenv pdesc instrs ppl =
let exe_instr instr (p, path) = let exe_instr instr (p, path) =
L.d_str "Executing Generated Instruction " ; L.d_str "Executing Generated Instruction " ;
Sil.d_instr instr ; Sil.d_instr instr ;
L.d_ln () ; L.d_ln () ;
try sym_exec tenv pdesc instr p path with exn -> try sym_exec exe_env tenv pdesc instr p path with exn ->
reraise_if exn ~f:(fun () -> not mask_errors || not (SymOp.exn_not_failure exn)) ; reraise_if exn ~f:(fun () -> not mask_errors || not (SymOp.exn_not_failure exn)) ;
let error = Exceptions.recognize_exception exn in let error = Exceptions.recognize_exception exn in
let loc = let loc =
@ -1575,7 +1578,7 @@ and unknown_or_scan_call ~is_scan ~reason ret_type_option ret_annots
and check_variadic_sentinel ?(fails_on_nil= false) n_formals (sentinel, null_pos) and check_variadic_sentinel ?(fails_on_nil= false) n_formals (sentinel, null_pos)
{Builtin.pdesc; tenv; prop_; path; args; proc_name; loc} = {Builtin.pdesc; tenv; prop_; path; args; proc_name; loc; exe_env} =
(* from clang's lib/Sema/SemaExpr.cpp: *) (* from clang's lib/Sema/SemaExpr.cpp: *)
(* "nullPos" is the number of formal parameters at the end which *) (* "nullPos" is the number of formal parameters at the end which *)
(* effectively count as part of the variadic arguments. This is *) (* effectively count as part of the variadic arguments. This is *)
@ -1594,7 +1597,7 @@ and check_variadic_sentinel ?(fails_on_nil= false) n_formals (sentinel, null_pos
(* simulate a Load for [lexp] *) (* simulate a Load for [lexp] *)
let tmp_id_deref = Ident.create_fresh Ident.kprimed in let tmp_id_deref = Ident.create_fresh Ident.kprimed in
let load_instr = Sil.Load (tmp_id_deref, lexp, typ, loc) in let load_instr = Sil.Load (tmp_id_deref, lexp, typ, loc) in
try instrs tenv pdesc [load_instr] result with e when SymOp.exn_not_failure e -> try instrs exe_env tenv pdesc [load_instr] result with e when SymOp.exn_not_failure e ->
reraise_if e ~f:(fun () -> fails_on_nil) ; reraise_if e ~f:(fun () -> fails_on_nil) ;
let deref_str = Localise.deref_str_nil_argument_in_variadic_method proc_name nargs i in let deref_str = Localise.deref_str_nil_argument_in_variadic_method proc_name nargs i in
let err_desc = let err_desc =
@ -1674,7 +1677,7 @@ and sym_exec_objc_accessor property_accesor ret_typ tenv ret_id pdesc _ loc args
f_accessor ret_typ tenv ret_id pdesc cur_pname loc args prop |> List.map ~f:(fun p -> (p, path)) f_accessor ret_typ tenv ret_id pdesc cur_pname loc args prop |> List.map ~f:(fun p -> (p, path))
and sym_exec_alloc_model pname ret_typ tenv ret_id pdesc loc prop path : Builtin.ret_typ = and sym_exec_alloc_model exe_env pname ret_typ tenv ret_id pdesc loc prop path : Builtin.ret_typ =
let alloc_source_function_arg = (Exp.Const (Const.Cfun pname), Typ.mk Tvoid) in let alloc_source_function_arg = (Exp.Const (Const.Cfun pname), Typ.mk Tvoid) in
let args = let args =
let sizeof_exp = let sizeof_exp =
@ -1686,11 +1689,11 @@ and sym_exec_alloc_model pname ret_typ tenv ret_id pdesc loc prop path : Builtin
let alloc_fun = Exp.Const (Const.Cfun BuiltinDecl.malloc_no_fail) in let alloc_fun = Exp.Const (Const.Cfun BuiltinDecl.malloc_no_fail) in
let alloc_instr = Sil.Call (ret_id, alloc_fun, args, loc, CallFlags.default) in let alloc_instr = Sil.Call (ret_id, alloc_fun, args, loc, CallFlags.default) in
L.d_strln "No spec found, method should be model as alloc, executing alloc... " ; L.d_strln "No spec found, method should be model as alloc, executing alloc... " ;
instrs tenv pdesc [alloc_instr] [(prop, path)] instrs exe_env tenv pdesc [alloc_instr] [(prop, path)]
(** Perform symbolic execution for a function call *) (** Perform symbolic execution for a function call *)
and proc_call callee_summary and proc_call exe_env callee_summary
{Builtin.pdesc; tenv; prop_= pre; path; ret_id; args= actual_pars; loc} = {Builtin.pdesc; tenv; prop_= pre; path; ret_id; args= actual_pars; loc} =
let caller_pname = Procdesc.get_proc_name pdesc in let caller_pname = Procdesc.get_proc_name pdesc in
let callee_attrs = Specs.get_attributes callee_summary in let callee_attrs = Specs.get_attributes callee_summary in
@ -1737,15 +1740,15 @@ and proc_call callee_summary
| Language.Clang, ProcAttributes.OBJC_INSTANCE -> | Language.Clang, ProcAttributes.OBJC_INSTANCE ->
handle_objc_instance_method_call actual_pars actual_params pre tenv ret_id pdesc callee_pname handle_objc_instance_method_call actual_pars actual_params pre tenv ret_id pdesc callee_pname
loc path loc path
(Tabulation.exe_function_call callee_summary) (Tabulation.exe_function_call exe_env callee_summary)
| _ -> | _ ->
(* non-objective-c method call. Standard tabulation *) (* non-objective-c method call. Standard tabulation *)
Tabulation.exe_function_call callee_summary tenv ret_id pdesc callee_pname loc actual_params Tabulation.exe_function_call exe_env callee_summary tenv ret_id pdesc callee_pname loc
pre path actual_params pre path
(** perform symbolic execution for a single prop, and check for junk *) (** perform symbolic execution for a single prop, and check for junk *)
and sym_exec_wrapper handle_exn tenv proc_cfg instr ((prop: Prop.normal Prop.t), path) and sym_exec_wrapper exe_env handle_exn tenv proc_cfg instr ((prop: Prop.normal Prop.t), path)
: Paths.PathSet.t = : Paths.PathSet.t =
let pname = Procdesc.get_proc_name (ProcCfg.Exceptional.proc_desc proc_cfg) in let pname = Procdesc.get_proc_name (ProcCfg.Exceptional.proc_desc proc_cfg) in
let prop_primed_to_normal p = let prop_primed_to_normal p =
@ -1804,7 +1807,8 @@ and sym_exec_wrapper handle_exn tenv proc_cfg instr ((prop: Prop.normal Prop.t),
let res_list = let res_list =
Config.run_with_abs_val_equal_zero Config.run_with_abs_val_equal_zero
(* no exp abstraction during sym exe *) (* no exp abstraction during sym exe *)
(fun () -> sym_exec tenv (ProcCfg.Exceptional.proc_desc proc_cfg) instr prop' path ) (fun () ->
sym_exec exe_env tenv (ProcCfg.Exceptional.proc_desc proc_cfg) instr prop' path )
() ()
in in
let res_list_nojunk = let res_list_nojunk =
@ -1829,7 +1833,7 @@ and sym_exec_wrapper handle_exn tenv proc_cfg instr ((prop: Prop.normal Prop.t),
(** {2 Lifted Abstract Transfer Functions} *) (** {2 Lifted Abstract Transfer Functions} *)
let node handle_exn tenv proc_cfg (node: ProcCfg.Exceptional.node) (pset: Paths.PathSet.t) let node handle_exn exe_env tenv proc_cfg (node: ProcCfg.Exceptional.node) (pset: Paths.PathSet.t)
: Paths.PathSet.t = : Paths.PathSet.t =
let pname = Procdesc.get_proc_name (ProcCfg.Exceptional.proc_desc proc_cfg) in let pname = Procdesc.get_proc_name (ProcCfg.Exceptional.proc_desc proc_cfg) in
let exe_instr_prop instr p tr (pset1: Paths.PathSet.t) = let exe_instr_prop instr p tr (pset1: Paths.PathSet.t) =
@ -1843,7 +1847,7 @@ let node handle_exn tenv proc_cfg (node: ProcCfg.Exceptional.node) (pset: Paths.
Sil.d_instr instr ; Sil.d_instr instr ;
L.d_strln " due to exception" ; L.d_strln " due to exception" ;
Paths.PathSet.from_renamed_list [(p, tr)] ) Paths.PathSet.from_renamed_list [(p, tr)] )
else sym_exec_wrapper handle_exn tenv proc_cfg instr (p, tr) else sym_exec_wrapper exe_env handle_exn tenv proc_cfg instr (p, tr)
in in
Paths.PathSet.union pset2 pset1 Paths.PathSet.union pset2 pset1
in in

@ -13,12 +13,12 @@ open! IStd
(** Symbolic Execution *) (** Symbolic Execution *)
val node : val node :
(exn -> unit) -> Tenv.t -> ProcCfg.Exceptional.t -> ProcCfg.Exceptional.node -> Paths.PathSet.t (exn -> unit) -> Exe_env.t -> Tenv.t -> ProcCfg.Exceptional.t -> ProcCfg.Exceptional.node
-> Paths.PathSet.t -> Paths.PathSet.t -> Paths.PathSet.t
(** Symbolic execution of the instructions of a node, lifted to sets of propositions. *) (** Symbolic execution of the instructions of a node, lifted to sets of propositions. *)
val instrs : val instrs :
?mask_errors:bool -> Tenv.t -> Procdesc.t -> Sil.instr list ?mask_errors:bool -> Exe_env.t -> Tenv.t -> Procdesc.t -> Sil.instr list
-> (Prop.normal Prop.t * Paths.Path.t) list -> (Prop.normal Prop.t * Paths.Path.t) list -> (Prop.normal Prop.t * Paths.Path.t) list -> (Prop.normal Prop.t * Paths.Path.t) list
(** Symbolic execution of a sequence of instructions. (** Symbolic execution of a sequence of instructions.
If errors occur and [mask_errors] is true, just treat as skip. *) If errors occur and [mask_errors] is true, just treat as skip. *)
@ -26,7 +26,7 @@ val instrs :
val diverge : Prop.normal Prop.t -> Paths.Path.t -> (Prop.normal Prop.t * Paths.Path.t) list val diverge : Prop.normal Prop.t -> Paths.Path.t -> (Prop.normal Prop.t * Paths.Path.t) list
(** Symbolic execution of the divergent pure computation. *) (** Symbolic execution of the divergent pure computation. *)
val proc_call : Specs.summary -> Builtin.t val proc_call : Exe_env.t -> Specs.summary -> Builtin.t
val unknown_or_scan_call : val unknown_or_scan_call :
is_scan:bool -> reason:string -> Typ.t option -> Annot.Item.t -> Builtin.t is_scan:bool -> reason:string -> Typ.t option -> Annot.Item.t -> Builtin.t

@ -1084,22 +1084,16 @@ let missing_sigma_need_adding_to_tenv tenv hpreds =
List.exists hpreds ~f:missing_hpred_need_adding_to_tenv List.exists hpreds ~f:missing_hpred_need_adding_to_tenv
let add_missing_field_to_tenv ~missing_sigma caller_tenv callee_pname hpreds = let add_missing_field_to_tenv ~missing_sigma exe_env caller_tenv callee_pname hpreds =
(* if hpreds are missing_sigma, we may not need to add the fields to the tenv, so we check that first *) (* if hpreds are missing_sigma, we may not need to add the fields to the tenv, so we check that first *)
let add_fields = let add_fields =
if missing_sigma then missing_sigma_need_adding_to_tenv caller_tenv hpreds else true if missing_sigma then missing_sigma_need_adding_to_tenv caller_tenv hpreds else true
in in
if add_fields then if add_fields then
match Ondemand.get_proc_desc callee_pname with let callee_tenv = Exe_env.get_tenv exe_env callee_pname in
| Some pdesc ->
let attrs = Procdesc.get_attributes pdesc in
let source_file = attrs.ProcAttributes.loc.Location.file in
let callee_tenv_opt = Tenv.load source_file in
let add_field_in_hpred hpred = let add_field_in_hpred hpred =
match (callee_tenv_opt, hpred) with match hpred with
| ( Some callee_tenv | Sil.Hpointsto (_, Sil.Estruct (_, _), Exp.Sizeof {typ= {desc= Typ.Tstruct name}}) -> (
, Sil.Hpointsto (_, Sil.Estruct (_, _), Exp.Sizeof {typ= {desc= Typ.Tstruct name}}) )
-> (
match Tenv.lookup callee_tenv name with match Tenv.lookup callee_tenv name with
| Some {fields} -> | Some {fields} ->
List.iter ~f:(fun field -> Tenv.add_field caller_tenv name field) fields List.iter ~f:(fun field -> Tenv.add_field caller_tenv name field) fields
@ -1109,12 +1103,10 @@ let add_missing_field_to_tenv ~missing_sigma caller_tenv callee_pname hpreds =
() ()
in in
List.iter ~f:add_field_in_hpred hpreds List.iter ~f:add_field_in_hpred hpreds
| None ->
()
(** Perform symbolic execution for a single spec *) (** Perform symbolic execution for a single spec *)
let exe_spec tenv ret_id_opt (n, nspecs) caller_pdesc callee_pname loc prop path_pre let exe_spec exe_env tenv ret_id_opt (n, nspecs) caller_pdesc callee_pname loc prop path_pre
(spec: Prop.exposed Specs.spec) actual_params formal_params : abduction_res = (spec: Prop.exposed Specs.spec) actual_params formal_params : abduction_res =
let caller_pname = Procdesc.get_proc_name caller_pdesc in let caller_pname = Procdesc.get_proc_name caller_pdesc in
let posts = mk_posts tenv ret_id_opt prop callee_pname spec.Specs.posts in let posts = mk_posts tenv ret_id_opt prop callee_pname spec.Specs.posts in
@ -1213,10 +1205,11 @@ let exe_spec tenv ret_id_opt (n, nspecs) caller_pdesc callee_pname loc prop path
in in
if missing_fld_objc_class <> [] then ( if missing_fld_objc_class <> [] then (
L.d_strln "Objective-C missing_fld not empty: adding it to current tenv..." ; L.d_strln "Objective-C missing_fld not empty: adding it to current tenv..." ;
add_missing_field_to_tenv ~missing_sigma:false tenv callee_pname missing_fld_objc_class ) ; add_missing_field_to_tenv ~missing_sigma:false exe_env tenv callee_pname
missing_fld_objc_class ) ;
if missing_sigma_objc_class <> [] then ( if missing_sigma_objc_class <> [] then (
L.d_strln "Objective-C missing_sigma not empty: adding it to current tenv..." ; L.d_strln "Objective-C missing_sigma not empty: adding it to current tenv..." ;
add_missing_field_to_tenv ~missing_sigma:true tenv callee_pname add_missing_field_to_tenv ~missing_sigma:true exe_env tenv callee_pname
missing_sigma_objc_class ) ; missing_sigma_objc_class ) ;
if not !Config.footprint && split.missing_sigma <> [] then ( if not !Config.footprint && split.missing_sigma <> [] then (
L.d_strln "Implication error: missing_sigma not empty in re-execution" ; L.d_strln "Implication error: missing_sigma not empty in re-execution" ;
@ -1435,8 +1428,8 @@ let exe_call_postprocess tenv ret_id trace_call caller_pname callee_pname callee
(** Execute the function call and return the list of results with return value *) (** Execute the function call and return the list of results with return value *)
let exe_function_call callee_summary tenv ret_id_opt caller_pdesc callee_pname loc actual_params let exe_function_call exe_env callee_summary tenv ret_id_opt caller_pdesc callee_pname loc
prop path = actual_params prop path =
let callee_attrs = Specs.get_attributes callee_summary in let callee_attrs = Specs.get_attributes callee_summary in
let caller_pname = Procdesc.get_proc_name caller_pdesc in let caller_pname = Procdesc.get_proc_name caller_pdesc in
let trace_call = log_call_trace caller_pname callee_pname loc in let trace_call = log_call_trace caller_pname callee_pname loc in
@ -1449,8 +1442,8 @@ let exe_function_call callee_summary tenv ret_id_opt caller_pdesc callee_pname l
Prop.d_prop prop ; Prop.d_prop prop ;
L.d_ln () ; L.d_ln () ;
let exe_one_spec (n, spec) = let exe_one_spec (n, spec) =
exe_spec tenv ret_id_opt (n, nspecs) caller_pdesc callee_pname loc prop path spec actual_params exe_spec exe_env tenv ret_id_opt (n, nspecs) caller_pdesc callee_pname loc prop path spec
formal_params actual_params formal_params
in in
let results = List.map ~f:exe_one_spec spec_list in let results = List.map ~f:exe_one_spec spec_list in
exe_call_postprocess tenv ret_id_opt trace_call caller_pname callee_pname callee_attrs loc exe_call_postprocess tenv ret_id_opt trace_call caller_pname callee_pname callee_attrs loc

@ -47,7 +47,7 @@ val lookup_custom_errors : 'a Prop.t -> string option
(** search in prop contains an error state *) (** search in prop contains an error state *)
val exe_function_call : val exe_function_call :
Specs.summary -> Tenv.t -> (Ident.t * Typ.t) option -> Procdesc.t -> Typ.Procname.t -> Location.t Exe_env.t -> Specs.summary -> Tenv.t -> (Ident.t * Typ.t) option -> Procdesc.t -> Typ.Procname.t
-> (Exp.t * Typ.t) list -> Prop.normal Prop.t -> Paths.Path.t -> Location.t -> (Exp.t * Typ.t) list -> Prop.normal Prop.t -> Paths.Path.t
-> (Prop.normal Prop.t * Paths.Path.t) list -> (Prop.normal Prop.t * Paths.Path.t) list
(** Execute the function call and return the list of results with return value *) (** Execute the function call and return the list of results with return value *)

Loading…
Cancel
Save