@ -38,7 +38,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
)
| None -> true
let get_globals tenv pdesc e =
let get_globals tenv astate pdesc lo c e =
let is_dangerous_global pv =
Pvar . is_global pv
&& not ( Pvar . is_compile_constant pv
@ -47,32 +47,44 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
if globals = [] then
Domain . Bottom
else
Domain . NonBottom ( SiofDomain . PvarSetDomain . of_list globals )
let add_params_globals astate tenv pdesc params =
let sink_of_global global pname loc =
let site = CallSite . make pname loc in
SiofTrace . Sink . make global site in
let pname = Cfg . Procdesc . get_proc_name pdesc in
let trace = match astate with
| Domain . Bottom -> SiofTrace . initial
| Domain . NonBottom t -> t in
let globals_trace =
IList . fold_left ( fun trace_acc global ->
SiofTrace . add_sink ( sink_of_global global pname loc ) trace_acc )
trace
globals in
Domain . NonBottom globals_trace
let add_params_globals astate tenv pdesc loc params =
IList . map fst params
| > IList . map ( fun e -> get_globals tenv pdesc e )
| > IList . map ( fun e -> get_globals tenv astate pdesc lo c e )
| > IList . fold_left Domain . join astate
let at_least_bottom =
Domain . join ( Domain . NonBottom SiofDomain . PvarSetDomain . empty )
Domain . join ( Domain . NonBottom Siof Trace. initial )
let exec_instr astate { ProcData . pdesc ; tenv } _ ( instr : Sil . instr ) = match instr with
| Load ( _ , exp , _ , _ )
| Store ( _ , _ , exp , _ )
| Prune ( exp , _ , _ , _ ) ->
Domain . join astate ( get_globals tenv pdesc exp )
| Call ( _ , Const ( Cfun callee_pname ) , params , _ , _ ) ->
| Load ( _ , exp , _ , loc )
| Store ( _ , _ , exp , loc )
| Prune ( exp , loc , _ , _ ) ->
Domain . join astate ( get_globals tenv astate pdesc lo c exp )
| Call ( _ , Const ( Cfun callee_pname ) , params , loc , _ ) ->
let callee_globals =
Option . default Domain . initial
@@ Summary . read_summary tenv pdesc callee_pname in
add_params_globals astate tenv pdesc params
add_params_globals astate tenv pdesc loc params
| > Domain . join callee_globals
| >
(* make sure it's not Bottom: we made a function call so this needs initialization *)
at_least_bottom
| Call ( _ , _ , params , _ , _ ) ->
add_params_globals astate tenv pdesc params
| Call ( _ , _ , params , loc , _ ) ->
add_params_globals astate tenv pdesc loc params
| >
(* make sure it's not Bottom: we made a function call so this needs initialization *)
at_least_bottom
@ -99,14 +111,14 @@ let report_siof pname loc bad_globals =
| Some source_file ->
Format . fprintf f " from file %s " ( DB . source_file_to_string source_file ) in
Format . fprintf f " %s%a " ( Pvar . get_simplified_name v ) pp_source v in
let pp_set f s = pp_seq pp_var f ( Pvar . Set . elements s ) in
let pp_set f s = pp_seq pp_var f s in
Format . fprintf fmt
" This global variable initializer accesses the following globals in another translation \
unit : % a "
pp_set bad_globals in
let description = pp_to_string pp_desc () in
let msg = Localise . to_string Localise . static_initialization_order_fiasco in
let exn = Exceptions . Checkers ( msg , Localise . verbatim_desc description ) in
let exn = Exceptions . Checkers
( " STATIC_INITIALIZATION_ORDER_FIASCO " , Localise . verbatim_desc description ) in
Reporting . log_error pname ~ loc exn
@ -120,8 +132,16 @@ let siof_check pdesc = function
| None -> false in
let is_foreign v = Option . map_default
( fun f -> not ( is_orig_file f ) ) false ( Pvar . get_source_file v ) in
let foreign_globals = SiofDomain . PvarSetDomain . filter is_foreign post in
if not ( SiofDomain . PvarSetDomain . is_empty foreign_globals ) then
let foreign_global_sinks =
SiofTrace . Sinks . filter
( fun sink -> is_foreign ( SiofTrace . Sink . kind sink ) )
( SiofTrace . sinks post ) in
if not ( SiofTrace . Sinks . is_empty foreign_global_sinks )
then
let foreign_globals =
IList . map
( fun sink -> ( SiofTrace . Sink . kind sink ) )
( SiofTrace . Sinks . elements foreign_global_sinks ) in
report_siof ( Cfg . Procdesc . get_proc_name pdesc ) attrs . ProcAttributes . loc foreign_globals ;
| Some SiofDomain . Bottom | None ->
()