|
|
@ -499,13 +499,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
|
|
|
|
we own the container *)
|
|
|
|
we own the container *)
|
|
|
|
let escapee_formals = List.length actuals |> List.range 0 |> FormalsDomain.of_list in
|
|
|
|
let escapee_formals = List.length actuals |> List.range 0 |> FormalsDomain.of_list in
|
|
|
|
Some
|
|
|
|
Some
|
|
|
|
( true
|
|
|
|
{ thumbs_up= true
|
|
|
|
, false
|
|
|
|
; locks= false
|
|
|
|
, false
|
|
|
|
; threads= false
|
|
|
|
, callee_accesses
|
|
|
|
; accesses= callee_accesses
|
|
|
|
, OwnershipAbstractValue.unowned
|
|
|
|
; return_ownership= OwnershipAbstractValue.unowned
|
|
|
|
, AttributeSetDomain.empty
|
|
|
|
; return_attributes= AttributeSetDomain.empty
|
|
|
|
, escapee_formals )
|
|
|
|
; escapee_formals }
|
|
|
|
|
|
|
|
|
|
|
|
let get_summary caller_pdesc callee_pname actuals callee_loc tenv =
|
|
|
|
let get_summary caller_pdesc callee_pname actuals callee_loc tenv =
|
|
|
|
let get_receiver_ap actuals =
|
|
|
|
let get_receiver_ap actuals =
|
|
|
@ -627,13 +627,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
|
|
|
|
| NoEffect ->
|
|
|
|
| NoEffect ->
|
|
|
|
match get_summary pdesc callee_pname actuals loc tenv with
|
|
|
|
match get_summary pdesc callee_pname actuals loc tenv with
|
|
|
|
| Some
|
|
|
|
| Some
|
|
|
|
( callee_thumbs_up
|
|
|
|
{ thumbs_up
|
|
|
|
, callee_threads
|
|
|
|
; threads
|
|
|
|
, callee_locks
|
|
|
|
; locks
|
|
|
|
, callee_accesses
|
|
|
|
; accesses
|
|
|
|
, return_ownership
|
|
|
|
; return_ownership
|
|
|
|
, return_attributes
|
|
|
|
; return_attributes
|
|
|
|
, escapee_formals )
|
|
|
|
; escapee_formals }
|
|
|
|
-> let update_caller_accesses pre callee_accesses caller_accesses =
|
|
|
|
-> let update_caller_accesses pre callee_accesses caller_accesses =
|
|
|
|
let combined_accesses =
|
|
|
|
let combined_accesses =
|
|
|
|
PathDomain.with_callsite callee_accesses (CallSite.make callee_pname loc)
|
|
|
|
PathDomain.with_callsite callee_accesses (CallSite.make callee_pname loc)
|
|
|
@ -641,9 +641,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
|
|
|
|
in
|
|
|
|
in
|
|
|
|
AccessDomain.add pre combined_accesses caller_accesses
|
|
|
|
AccessDomain.add pre combined_accesses caller_accesses
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let thumbs_up = callee_thumbs_up && astate.thumbs_up in
|
|
|
|
let thumbs_up = thumbs_up && astate.thumbs_up in
|
|
|
|
let locks = callee_locks || astate.locks in
|
|
|
|
let locks = locks || astate.locks in
|
|
|
|
let threads = callee_threads || astate.threads in
|
|
|
|
let threads = threads || astate.threads in
|
|
|
|
let unprotected = is_unprotected locks threads pdesc in
|
|
|
|
let unprotected = is_unprotected locks threads pdesc in
|
|
|
|
(* add [ownership_accesses] to the [accesses_acc] with a protected pre if
|
|
|
|
(* add [ownership_accesses] to the [accesses_acc] with a protected pre if
|
|
|
|
[exp] is owned, and an appropriate unprotected pre otherwise *)
|
|
|
|
[exp] is owned, and an appropriate unprotected pre otherwise *)
|
|
|
@ -707,7 +707,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
|
|
|
|
add_ownership_access callee_accesses (List.nth_exn actuals index) acc)
|
|
|
|
add_ownership_access callee_accesses (List.nth_exn actuals index) acc)
|
|
|
|
formal_indexes accesses_acc
|
|
|
|
formal_indexes accesses_acc
|
|
|
|
in
|
|
|
|
in
|
|
|
|
AccessDomain.fold update_accesses callee_accesses astate.accesses
|
|
|
|
AccessDomain.fold update_accesses accesses astate.accesses
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let ownership, attribute_map =
|
|
|
|
let ownership, attribute_map =
|
|
|
|
propagate_return ret_opt return_ownership return_attributes actuals astate
|
|
|
|
propagate_return ret_opt return_ownership return_attributes actuals astate
|
|
|
@ -841,7 +841,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
|
|
|
|
-> (* non-boolean expression; can't evaluate it *)
|
|
|
|
-> (* non-boolean expression; can't evaluate it *)
|
|
|
|
None
|
|
|
|
None
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let add_choice bool_value acc = function
|
|
|
|
let add_choice bool_value (acc: Domain.astate) = function
|
|
|
|
| Choice.LockHeld
|
|
|
|
| Choice.LockHeld
|
|
|
|
-> let locks = bool_value in
|
|
|
|
-> let locks = bool_value in
|
|
|
|
{acc with locks}
|
|
|
|
{acc with locks}
|
|
|
@ -963,20 +963,14 @@ let is_thread_safe_method pdesc tenv =
|
|
|
|
is_thread_safe)
|
|
|
|
is_thread_safe)
|
|
|
|
tenv (Procdesc.get_proc_name pdesc)
|
|
|
|
tenv (Procdesc.get_proc_name pdesc)
|
|
|
|
|
|
|
|
|
|
|
|
let empty_post =
|
|
|
|
let empty_post : ThreadSafetyDomain.summary =
|
|
|
|
let initial_thumbs_up = true
|
|
|
|
{ ThreadSafetyDomain.thumbs_up= true
|
|
|
|
and initial_known_on_ui_thread = false
|
|
|
|
; threads= false
|
|
|
|
and has_lock = false
|
|
|
|
; locks= false
|
|
|
|
and return_ownership = ThreadSafetyDomain.OwnershipAbstractValue.unowned
|
|
|
|
; accesses= ThreadSafetyDomain.AccessDomain.empty
|
|
|
|
and return_attrs = ThreadSafetyDomain.AttributeSetDomain.empty
|
|
|
|
; return_ownership= ThreadSafetyDomain.OwnershipAbstractValue.unowned
|
|
|
|
and escapee_formals = ThreadSafetyDomain.FormalsDomain.empty in
|
|
|
|
; return_attributes= ThreadSafetyDomain.AttributeSetDomain.empty
|
|
|
|
( initial_thumbs_up
|
|
|
|
; escapee_formals= ThreadSafetyDomain.FormalsDomain.empty }
|
|
|
|
, initial_known_on_ui_thread
|
|
|
|
|
|
|
|
, has_lock
|
|
|
|
|
|
|
|
, ThreadSafetyDomain.AccessDomain.empty
|
|
|
|
|
|
|
|
, return_ownership
|
|
|
|
|
|
|
|
, return_attrs
|
|
|
|
|
|
|
|
, escapee_formals )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
|
|
|
|
let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
|
|
|
|
let is_initializer tenv proc_name =
|
|
|
|
let is_initializer tenv proc_name =
|
|
|
@ -1035,13 +1029,13 @@ let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let escapee_formals = FormalsDomain.of_escapees escapees in
|
|
|
|
let escapee_formals = FormalsDomain.of_escapees escapees in
|
|
|
|
let post =
|
|
|
|
let post =
|
|
|
|
( thumbs_up
|
|
|
|
{ thumbs_up
|
|
|
|
, threads
|
|
|
|
; threads
|
|
|
|
, locks
|
|
|
|
; locks
|
|
|
|
, accesses
|
|
|
|
; accesses
|
|
|
|
, return_ownership
|
|
|
|
; return_ownership
|
|
|
|
, return_attributes
|
|
|
|
; return_attributes
|
|
|
|
, escapee_formals )
|
|
|
|
; escapee_formals }
|
|
|
|
in
|
|
|
|
in
|
|
|
|
Summary.update_summary post summary
|
|
|
|
Summary.update_summary post summary
|
|
|
|
| None
|
|
|
|
| None
|
|
|
@ -1141,10 +1135,10 @@ let trace_of_pname orig_sink orig_pdesc callee_pname =
|
|
|
|
let open ThreadSafetyDomain in
|
|
|
|
let open ThreadSafetyDomain in
|
|
|
|
let orig_access = PathDomain.Sink.kind orig_sink in
|
|
|
|
let orig_access = PathDomain.Sink.kind orig_sink in
|
|
|
|
match Summary.read_summary orig_pdesc callee_pname with
|
|
|
|
match Summary.read_summary orig_pdesc callee_pname with
|
|
|
|
| Some (_, _, _, access_map, _, _, _)
|
|
|
|
| Some {accesses}
|
|
|
|
-> get_all_accesses
|
|
|
|
-> get_all_accesses
|
|
|
|
(fun access -> Int.equal (Access.compare (PathDomain.Sink.kind access) orig_access) 0)
|
|
|
|
(fun access -> Int.equal (Access.compare (PathDomain.Sink.kind access) orig_access) 0)
|
|
|
|
access_map
|
|
|
|
accesses
|
|
|
|
| _
|
|
|
|
| _
|
|
|
|
-> PathDomain.empty
|
|
|
|
-> PathDomain.empty
|
|
|
|
|
|
|
|
|
|
|
@ -1578,8 +1572,8 @@ let should_filter_access access =
|
|
|
|
now, our abstraction is an access path like x.f.g whose concretization is the set of memory cells
|
|
|
|
now, our abstraction is an access path like x.f.g whose concretization is the set of memory cells
|
|
|
|
that x.f.g may point to during execution *)
|
|
|
|
that x.f.g may point to during execution *)
|
|
|
|
let make_results_table file_env =
|
|
|
|
let make_results_table file_env =
|
|
|
|
let aggregate_post (_, threaded, _, accesses, _, _, _) tenv pdesc acc =
|
|
|
|
let open ThreadSafetyDomain in
|
|
|
|
let open ThreadSafetyDomain in
|
|
|
|
let aggregate_post {threads; accesses} tenv pdesc acc =
|
|
|
|
AccessDomain.fold
|
|
|
|
AccessDomain.fold
|
|
|
|
(fun pre accesses acc ->
|
|
|
|
(fun pre accesses acc ->
|
|
|
|
PathDomain.Sinks.fold
|
|
|
|
PathDomain.Sinks.fold
|
|
|
@ -1592,7 +1586,7 @@ let make_results_table file_env =
|
|
|
|
with Not_found -> []
|
|
|
|
with Not_found -> []
|
|
|
|
in
|
|
|
|
in
|
|
|
|
AccessListMap.add access_kind
|
|
|
|
AccessListMap.add access_kind
|
|
|
|
((access, pre, threaded, tenv, pdesc) :: grouped_accesses) acc)
|
|
|
|
((access, pre, threads, tenv, pdesc) :: grouped_accesses) acc)
|
|
|
|
(PathDomain.sinks accesses) acc)
|
|
|
|
(PathDomain.sinks accesses) acc)
|
|
|
|
accesses acc
|
|
|
|
accesses acc
|
|
|
|
in
|
|
|
|
in
|
|
|
|