@ -698,17 +698,19 @@ type resolve_and_analyze_result =
(* * Resolve the procedure name and run the analysis of the resolved procedure
(* * Resolve the procedure name and run the analysis of the resolved procedure
if not already analyzed * )
if not already analyzed * )
let resolve_and_analyze tenv ~ caller_ pdesc ? ( has_clang_model = false ) prop args callee_proc_name
let resolve_and_analyze tenv ~ caller_ summary ? ( has_clang_model = false ) prop args callee_proc_name
call_flags : resolve_and_analyze_result =
call_flags : resolve_and_analyze_result =
(* TODO ( #15748878 ) : Fix conflict with method overloading by encoding in the procedure name
(* TODO ( #15748878 ) : Fix conflict with method overloading by encoding in the procedure name
whether the method is defined or generated by the specialization * )
whether the method is defined or generated by the specialization * )
let analyze_ondemand resolved_pname : Procdesc . t option * Summary . t option =
let analyze_ondemand resolved_pname : Procdesc . t option * Summary . t option =
if Typ . Procname . equal resolved_pname callee_proc_name then
if Typ . Procname . equal resolved_pname callee_proc_name then
( Ondemand . get_proc_desc callee_proc_name
( Ondemand . get_proc_desc callee_proc_name
, Ondemand . analyze_proc_name ~ caller_ pdesc callee_proc_name )
, Ondemand . analyze_proc_name ~ caller_ summary callee_proc_name )
else
else
(* Create the type specialized procedure description and analyze it directly *)
(* Create the type specialized procedure description and analyze it directly *)
let analyze specialized_pdesc = Ondemand . analyze_proc_desc ~ caller_pdesc specialized_pdesc in
let analyze specialized_pdesc =
Ondemand . analyze_proc_desc ~ caller_summary specialized_pdesc
in
let resolved_proc_desc_option =
let resolved_proc_desc_option =
match Ondemand . get_proc_desc resolved_pname with
match Ondemand . get_proc_desc resolved_pname with
| Some _ as resolved_proc_desc ->
| Some _ as resolved_proc_desc ->
@ -724,7 +726,11 @@ let resolve_and_analyze tenv ~caller_pdesc ?(has_clang_model = false) prop args
in
in
( resolved_proc_desc_option , Option . bind resolved_proc_desc_option ~ f : analyze )
( resolved_proc_desc_option , Option . bind resolved_proc_desc_option ~ f : analyze )
in
in
let resolved_pname = resolve_pname ~ caller_pdesc tenv prop args callee_proc_name call_flags in
let resolved_pname =
resolve_pname
~ caller_pdesc : ( Summary . get_proc_desc caller_summary )
tenv prop args callee_proc_name call_flags
in
let dynamic_dispatch_status =
let dynamic_dispatch_status =
if Typ . Procname . equal callee_proc_name resolved_pname then None
if Typ . Procname . equal callee_proc_name resolved_pname then None
else Some EventLogger . Dynamic_dispatch_successful
else Some EventLogger . Dynamic_dispatch_successful
@ -1092,8 +1098,8 @@ let is_variadic_procname callee_pname =
~ default : false
~ default : false
let resolve_and_analyze_no_dynamic_dispatch current_ pdesc tenv prop_r n_actual_params callee_pname
let resolve_and_analyze_no_dynamic_dispatch current_ summary tenv prop_r n_actual_params
call _flags =
call ee_pname call _flags =
let resolved_pname =
let resolved_pname =
match resolve_virtual_pname tenv prop_r n_actual_params callee_pname call_flags with
match resolve_virtual_pname tenv prop_r n_actual_params callee_pname call_flags with
| resolved_pname :: _ ->
| resolved_pname :: _ ->
@ -1102,7 +1108,7 @@ let resolve_and_analyze_no_dynamic_dispatch current_pdesc tenv prop_r n_actual_p
callee_pname
callee_pname
in
in
let resolved_summary_opt =
let resolved_summary_opt =
Ondemand . analyze_proc_name ~ caller_ pdesc: current_pdesc resolved_pname
Ondemand . analyze_proc_name ~ caller_ summary: current_summary resolved_pname
in
in
{ resolved_pname
{ resolved_pname
; resolved_procdesc_opt = Ondemand . get_proc_desc resolved_pname
; resolved_procdesc_opt = Ondemand . get_proc_desc resolved_pname
@ -1110,7 +1116,7 @@ let resolve_and_analyze_no_dynamic_dispatch current_pdesc tenv prop_r n_actual_p
; dynamic_dispatch_status = None }
; dynamic_dispatch_status = None }
let resolve_and_analyze_clang current_ pdesc tenv prop_r n_actual_params callee_pname call_flags =
let resolve_and_analyze_clang current_ summary tenv prop_r n_actual_params callee_pname call_flags =
if
if
Config . dynamic_dispatch
Config . dynamic_dispatch
&& ( not ( is_variadic_procname callee_pname ) )
&& ( not ( is_variadic_procname callee_pname ) )
@ -1121,7 +1127,7 @@ let resolve_and_analyze_clang current_pdesc tenv prop_r n_actual_params callee_p
try
try
let has_clang_model = Summary . has_model callee_pname in
let has_clang_model = Summary . has_model callee_pname in
let resolve_and_analyze_result =
let resolve_and_analyze_result =
resolve_and_analyze tenv ~ caller_ pdesc: current_pdesc ~ has_clang_model prop_r
resolve_and_analyze tenv ~ caller_ summary: current_summary ~ has_clang_model prop_r
n_actual_params callee_pname call_flags
n_actual_params callee_pname call_flags
in
in
(* It could be useful to specialize a model, but also it could cause a failure,
(* It could be useful to specialize a model, but also it could cause a failure,
@ -1138,7 +1144,7 @@ let resolve_and_analyze_clang current_pdesc tenv prop_r n_actual_params callee_p
in
in
if clang_model_specialized_failure then
if clang_model_specialized_failure then
let result =
let result =
resolve_and_analyze_no_dynamic_dispatch current_ pdesc tenv prop_r n_actual_params
resolve_and_analyze_no_dynamic_dispatch current_ summary tenv prop_r n_actual_params
callee_pname call_flags
callee_pname call_flags
in
in
{ result with
{ result with
@ -1147,14 +1153,14 @@ let resolve_and_analyze_clang current_pdesc tenv prop_r n_actual_params callee_p
else resolve_and_analyze_result
else resolve_and_analyze_result
with SpecializeProcdesc . UnmatchedParameters ->
with SpecializeProcdesc . UnmatchedParameters ->
let result =
let result =
resolve_and_analyze_no_dynamic_dispatch current_ pdesc tenv prop_r n_actual_params
resolve_and_analyze_no_dynamic_dispatch current_ summary tenv prop_r n_actual_params
callee_pname call_flags
callee_pname call_flags
in
in
{ result with
{ result with
dynamic_dispatch_status = Some EventLogger . Dynamic_dispatch_parameters_arguments_mismatch }
dynamic_dispatch_status = Some EventLogger . Dynamic_dispatch_parameters_arguments_mismatch }
else
else
resolve_and_analyze_no_dynamic_dispatch current_ pdesc tenv prop_r n_actual_params callee_pname
resolve_and_analyze_no_dynamic_dispatch current_ summary tenv prop_r n_actual_params
call _flags
call ee_pname call _flags
let declare_locals_and_ret tenv pdesc ( prop_ : Prop . normal Prop . t ) =
let declare_locals_and_ret tenv pdesc ( prop_ : Prop . normal Prop . t ) =
@ -1190,8 +1196,9 @@ let declare_locals_and_ret tenv pdesc (prop_ : Prop.normal Prop.t) =
(* * Execute [instr] with a symbolic heap [prop]. *)
(* * Execute [instr] with a symbolic heap [prop]. *)
let rec sym_exec exe_env tenv current_ pdesc instr_ ( prop_ : Prop . normal Prop . t ) path :
let rec sym_exec exe_env tenv current_ summary 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_pdesc = Summary . get_proc_desc current_summary in
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_ ;
(* mark instruction last seen *)
(* mark instruction last seen *)
@ -1231,7 +1238,7 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
? callee_attributes ~ reason loc Tabulation . CR_skip ;
? callee_attributes ~ reason loc Tabulation . CR_skip ;
unknown_or_scan_call ~ is_scan : false ~ reason ret_typ ret_annots
unknown_or_scan_call ~ is_scan : false ~ reason ret_typ ret_annots
Builtin .
Builtin .
{ pdesc= current_pdesc
{ summary= current_summary
; instr
; instr
; tenv
; tenv
; prop_ = prop
; prop_ = prop
@ -1248,7 +1255,7 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
else skip_res ()
else skip_res ()
in
in
let call_args prop_ proc_name args ret_id_typ loc =
let call_args prop_ proc_name args ret_id_typ loc =
{ Builtin . pdesc= current_pdesc
{ Builtin . summary= current_summary
; instr
; instr
; tenv
; tenv
; prop_
; prop_
@ -1314,8 +1321,8 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
norm_args
norm_args
in
in
let resolve_and_analyze_result =
let resolve_and_analyze_result =
resolve_and_analyze tenv ~ caller_ pdesc: current_pdesc norm_prop norm_args callee_pname
resolve_and_analyze tenv ~ caller_ summary: current_summary norm_prop norm_args
call _flags
call ee_pname call _flags
in
in
let resolved_pname = resolve_and_analyze_result . resolved_pname in
let resolved_pname = resolve_and_analyze_result . resolved_pname in
match resolve_and_analyze_result . resolved_summary_opt with
match resolve_and_analyze_result . resolved_summary_opt with
@ -1344,7 +1351,7 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
skip_call ~ reason norm_prop path pname ret_annots loc ret_id_typ ret_type
skip_call ~ reason norm_prop path pname ret_annots loc ret_id_typ ret_type
url_handled_args
url_handled_args
in
in
match Ondemand . analyze_proc_name ~ caller_ pdesc: current_pdesc pname with
match Ondemand . analyze_proc_name ~ caller_ summary: current_summary pname with
| None ->
| None ->
let ret_typ = Typ . Procname . Java . get_return_typ callee_pname_java in
let ret_typ = Typ . Procname . Java . get_return_typ callee_pname_java in
let ret_annots = load_ret_annots callee_pname in
let ret_annots = load_ret_annots callee_pname in
@ -1366,8 +1373,8 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
(* method with block parameters *)
(* method with block parameters *)
let with_block_parameters_summary_opt =
let with_block_parameters_summary_opt =
if call_flags . CallFlags . cf_with_block_parameters then
if call_flags . CallFlags . cf_with_block_parameters then
SymExecBlocks . resolve_method_with_block_args_and_analyze ~ caller_pdesc : current_pdesc
SymExecBlocks . resolve_method_with_block_args_and_analyze
callee_pname actual_params
~ caller_summary : current_summary callee_pname actual_params
else None
else None
in
in
match with_block_parameters_summary_opt with
match with_block_parameters_summary_opt with
@ -1381,7 +1388,7 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
| None ->
| None ->
(* Generic fun call with known name *)
(* Generic fun call with known name *)
let resolve_and_analyze_result =
let resolve_and_analyze_result =
resolve_and_analyze_clang current_ pdesc tenv prop_r n_actual_params callee_pname
resolve_and_analyze_clang current_ summary tenv prop_r n_actual_params callee_pname
call_flags
call_flags
in
in
let resolved_pname = resolve_and_analyze_result . resolved_pname in
let resolved_pname = resolve_and_analyze_result . resolved_pname in
@ -1431,7 +1438,7 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
| 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 exe_env resolved_pname ret_type tenv ret_id_typ
sym_exec_alloc_model exe_env resolved_pname ret_type tenv ret_id_typ
current_ pdesc loc prop path
current_ summary loc prop path
| None , false ->
| None , false ->
let is_objc_instance_method =
let is_objc_instance_method =
ClangMethodKind . equal attrs . ProcAttributes . clang_method_kind
ClangMethodKind . equal attrs . ProcAttributes . clang_method_kind
@ -1470,7 +1477,7 @@ let rec sym_exec exe_env tenv current_pdesc instr_ (prop_ : Prop.normal Prop.t)
unknown_or_scan_call ~ is_scan : false ~ reason : " unresolved function pointer " ( snd ret_id_typ )
unknown_or_scan_call ~ is_scan : false ~ reason : " unresolved function pointer " ( snd ret_id_typ )
Annot . Item . empty
Annot . Item . empty
Builtin .
Builtin .
{ pdesc= current_pdesc
{ summary= current_summary
; instr
; instr
; tenv
; tenv
; prop_ = prop_r
; prop_ = prop_r
@ -1521,12 +1528,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 ) exe_env tenv pdesc instrs ppl =
and instrs ? ( mask_errors = false ) exe_env tenv summary 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 exe_env tenv pdesc instr p path
try sym_exec exe_env tenv summary instr p path
with exn ->
with exn ->
IExn . reraise_if exn ~ f : ( fun () -> ( not mask_errors ) | | not ( SymOp . exn_not_failure exn ) ) ;
IExn . 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
@ -1633,7 +1640,7 @@ and add_constraints_on_actuals_by_ref tenv caller_pdesc prop actuals_by_ref call
(* * execute a call for an unknown or scan function *)
(* * execute a call for an unknown or scan function *)
and unknown_or_scan_call ~ is_scan ~ reason ret_typ ret_annots
and unknown_or_scan_call ~ is_scan ~ reason ret_typ ret_annots
{ Builtin . tenv ; pdesc ; prop_ = pre ; path ; ret_id_typ ; args ; proc_name = callee_pname ; loc ; instr }
{ Builtin . tenv ; summary ; prop_ = pre ; path ; ret_id_typ ; args ; proc_name = callee_pname ; loc ; instr }
=
=
let remove_file_attribute prop =
let remove_file_attribute prop =
let do_exp p ( e , _ ) =
let do_exp p ( e , _ ) =
@ -1689,6 +1696,7 @@ and unknown_or_scan_call ~is_scan ~reason ret_typ ret_annots
in
in
let has_nonnull_annot = Annotations . ia_is_nonnull ret_annots in
let has_nonnull_annot = Annotations . ia_is_nonnull ret_annots in
let pre_final =
let pre_final =
let pdesc = Summary . get_proc_desc summary in
(* in Java, assume that skip functions close resources passed as params *)
(* in Java, assume that skip functions close resources passed as params *)
let pre_1 = if Typ . Procname . is_java callee_pname then remove_file_attribute pre else pre in
let pre_1 = if Typ . Procname . is_java callee_pname then remove_file_attribute pre else pre in
let pre_2 =
let pre_2 =
@ -1720,7 +1728,7 @@ and unknown_or_scan_call ~is_scan ~reason ret_typ 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 ; exe_env } =
{ Builtin . summary ; 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 *)
@ -1739,7 +1747,7 @@ and check_variadic_sentinel ?(fails_on_nil = false) n_formals (sentinel, null_po
(* 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 exe_env tenv pdesc ( Instrs . singleton load_instr ) result
try instrs exe_env tenv summary ( Instrs . singleton load_instr ) result
with e when SymOp . exn_not_failure e ->
with e when SymOp . exn_not_failure e ->
IExn . reraise_if e ~ f : ( fun () -> fails_on_nil ) ;
IExn . 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
@ -1823,7 +1831,7 @@ and sym_exec_objc_accessor callee_pname property_accesor ret_typ tenv ret_id pde
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 exe_env pname ret_typ tenv ret_id_typ pdesc loc prop path :
and sym_exec_alloc_model exe_env pname ret_typ tenv ret_id_typ summary loc prop path :
Builtin . ret_typ =
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 =
@ -1836,13 +1844,13 @@ and sym_exec_alloc_model exe_env pname ret_typ tenv ret_id_typ pdesc loc prop pa
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_typ , alloc_fun , args , loc , CallFlags . default ) in
let alloc_instr = Sil . Call ( ret_id_typ , 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 exe_env tenv pdesc ( Instrs . singleton alloc_instr ) [ ( prop , path ) ]
instrs exe_env tenv summary ( Instrs . singleton alloc_instr ) [ ( prop , path ) ]
(* * Perform symbolic execution for a function call *)
(* * Perform symbolic execution for a function call *)
and proc_call ? dynamic_dispatch exe_env callee_summary
and proc_call ? dynamic_dispatch exe_env callee_summary
{ Builtin . pdesc ; tenv ; prop_ = pre ; path ; ret_id_typ ; args = actual_pars ; loc } =
{ Builtin . summary ; tenv ; prop_ = pre ; path ; ret_id_typ ; args = actual_pars ; loc } =
let caller_pname = Procdesc. get_proc_name pdesc in
let caller_pname = Summary. get_proc_name summary in
let callee_attrs = Summary . get_attributes callee_summary in
let callee_attrs = Summary . get_attributes callee_summary in
let callee_pname = Summary . get_proc_name callee_summary in
let callee_pname = Summary . get_proc_name callee_summary in
check_inherently_dangerous_function caller_pname callee_pname ;
check_inherently_dangerous_function caller_pname callee_pname ;
@ -1883,6 +1891,7 @@ and proc_call ?dynamic_dispatch exe_env callee_summary
let actual_params = comb actual_pars formal_types in
let actual_params = comb actual_pars formal_types in
(* In case we call an objc instance method we add an extra spec
(* In case we call an objc instance method we add an extra spec
where the receiver is null and the semantics of the call is nop * )
where the receiver is null and the semantics of the call is nop * )
let pdesc = Summary . get_proc_desc summary in
match ( ! Language . curr_language , callee_attrs . ProcAttributes . clang_method_kind ) with
match ( ! Language . curr_language , callee_attrs . ProcAttributes . clang_method_kind ) with
| Language . Clang , ClangMethodKind . OBJC_INSTANCE ->
| Language . Clang , ClangMethodKind . OBJC_INSTANCE ->
handle_objc_instance_method_call actual_pars actual_params pre tenv ( fst ret_id_typ ) pdesc
handle_objc_instance_method_call actual_pars actual_params pre tenv ( fst ret_id_typ ) pdesc
@ -1961,8 +1970,7 @@ and sym_exec_wrapper exe_env handle_exn tenv summary proc_cfg instr
let res_list =
let res_list =
BiabductionConfig . run_with_abs_val_equal_zero
BiabductionConfig . run_with_abs_val_equal_zero
(* no exp abstraction during sym exe *)
(* no exp abstraction during sym exe *)
( fun () ->
( fun () -> sym_exec exe_env tenv summary instr prop' path )
sym_exec exe_env tenv ( ProcCfg . Exceptional . proc_desc proc_cfg ) instr prop' path )
()
()
in
in
let res_list_nojunk =
let res_list_nojunk =