[AI] empty is not (necessarily) bottom

Reviewed By: mbouaziz

Differential Revision: D13358254

fbshipit-source-id: 7f5d7e409
master
Nikos Gorogiannis 6 years ago committed by Facebook Github Bot
parent 8a3592c34e
commit 764e9ee1be

@ -43,9 +43,9 @@ end
module type WithBottom = sig
include S
val empty : t
val bottom : t
val is_empty : t -> bool
val is_bottom : t -> bool
end
module type WithTop = sig
@ -59,9 +59,9 @@ end
module BottomLifted (Domain : S) = struct
type t = Domain.t bottom_lifted
let empty = Bottom
let bottom = Bottom
let is_empty = function Bottom -> true | NonBottom _ -> false
let is_bottom = function Bottom -> true | NonBottom _ -> false
let ( <= ) ~lhs ~rhs =
if phys_equal lhs rhs then true
@ -194,9 +194,9 @@ end
module Flat (V : PrettyPrintable.PrintableEquatableType) = struct
type t = Bot | V of V.t | Top
let empty = Bot
let bottom = Bot
let is_empty = function Bot -> true | _ -> false
let is_bottom = function Bot -> true | _ -> false
let top = Top
@ -249,6 +249,10 @@ end
module FiniteSetOfPPSet (S : PrettyPrintable.PPSet) = struct
include S
let bottom = empty
let is_bottom = is_empty
let ( <= ) ~lhs ~rhs = if phys_equal lhs rhs then true else subset lhs rhs
let join astate1 astate2 = if phys_equal astate1 astate2 then astate1 else union astate1 astate2
@ -292,6 +296,10 @@ module MapOfPPMap (M : PrettyPrintable.PPMap) (ValueDomain : S) = struct
type value = ValueDomain.t
let bottom = empty
let is_bottom = is_empty
(** true if all keys in [lhs] are in [rhs], and each lhs value <= corresponding rhs value *)
let ( <= ) ~lhs ~rhs =
if phys_equal lhs rhs then true
@ -405,9 +413,9 @@ struct
type t = M.t
let empty = M.empty
let bottom = M.empty
let is_empty = M.is_empty
let is_bottom = M.is_empty
let ( <= ) = M.( <= )
@ -449,9 +457,9 @@ end
module BooleanOr = struct
type t = bool
let empty = false
let bottom = false
let is_empty astate = not astate
let is_bottom astate = not astate
let ( <= ) ~lhs ~rhs = (not lhs) || rhs
@ -474,11 +482,11 @@ module CountDomain (MaxCount : MaxCount) = struct
MaxCount.max
let empty = 0
let bottom = 0
let is_top = Int.equal top
let is_empty = Int.equal empty
let is_bottom = Int.equal bottom
let ( <= ) ~lhs ~rhs = lhs <= rhs
@ -490,7 +498,7 @@ module CountDomain (MaxCount : MaxCount) = struct
let increment astate = if is_top astate then top else astate + 1
let decrement astate = if is_empty astate then empty else astate - 1
let decrement astate = if is_bottom astate then bottom else astate - 1
let pp = Int.pp
end

@ -45,12 +45,10 @@ end
module type WithBottom = sig
include S
val empty : t
(** The bottom value of the domain.
Naming it empty instead of bottom helps to bind the empty
value for sets and maps to the natural definition for bottom *)
val bottom : t
(** The bottom value of the domain. *)
val is_empty : t -> bool
val is_bottom : t -> bool
(** Return true if this is the bottom value *)
end

@ -687,7 +687,7 @@ module Alias = struct
AliasRet.pp x.ret
let bot : t = {map= AliasMap.empty; ret= AliasRet.empty}
let bot : t = {map= AliasMap.empty; ret= AliasRet.bottom}
let lift_map : (AliasMap.t -> AliasMap.t) -> t -> t = fun f a -> {a with map= f a.map}
@ -736,7 +736,7 @@ module CoreVal = struct
let is_symbolic v = Itv.is_symbolic (Val.get_itv v) || ArrayBlk.is_symbolic (Val.get_array_blk v)
let is_empty v = Itv.is_empty (Val.get_itv v) && ArrayBlk.is_empty (Val.get_array_blk v)
let is_empty v = Itv.is_bottom (Val.get_itv v) && ArrayBlk.is_empty (Val.get_array_blk v)
end
module PruningExp = struct
@ -1143,7 +1143,9 @@ module MemReach = struct
let add_heap : Loc.t -> Val.t -> t -> t =
fun x v m ->
let v =
let sym = if Itv.is_empty (Val.get_itv v) then Relation.Sym.bot else Relation.Sym.of_loc x in
let sym =
if Itv.is_bottom (Val.get_itv v) then Relation.Sym.bot else Relation.Sym.of_loc x
in
let offset_sym, size_sym =
if ArrayBlk.is_bot (Val.get_array_blk v) then (Relation.Sym.bot, Relation.Sym.bot)
else (Relation.Sym.of_loc_offset x, Relation.Sym.of_loc_size x)

@ -515,7 +515,7 @@ module Make (Manager : Manager_S) = struct
module Sym = struct
include AbstractDomain.Flat (Var)
let bot = empty
let bot = bottom
let lift f x = v (f x)

@ -11,6 +11,10 @@ module L = Logging
include (IdMap : module type of IdMap with type 'a t := 'a IdMap.t)
let bottom = empty
let is_bottom = is_empty
type t = HilExp.AccessExpression.t IdMap.t
type value = HilExp.AccessExpression.t

@ -50,7 +50,7 @@ module Make (TraceElem : TraceElem.S) = struct
type sink_path = Passthroughs.t * (Sink.t * Passthroughs.t) list
let empty =
let bottom =
let dummy_source = () in
of_source dummy_source
@ -70,13 +70,13 @@ module Make (TraceElem : TraceElem.S) = struct
~f:(fun t_acc sink ->
let callee_sink = Sink.with_callsite sink call_site in
add_sink callee_sink t_acc )
~init:empty
~init:bottom
(Sinks.elements (sinks t))
let of_sink sink =
let sinks = Sinks.add sink Sinks.empty in
update_sinks empty sinks
update_sinks bottom sinks
let get_reportable_sink_path sink ~trace_of_pname =

@ -113,7 +113,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let add_globals astate loc globals =
if GlobalVarSet.is_empty globals then astate
else
let trace = match fst astate with Bottom -> SiofTrace.empty | NonBottom t -> t in
let trace = match fst astate with Bottom -> SiofTrace.bottom | NonBottom t -> t in
let is_dangerous =
(* filter out variables that are known to be already initialized *)
let initialized = snd astate in
@ -134,7 +134,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
get_globals pdesc e |> add_globals astate call_loc )
let at_least_nonbottom = Domain.join (NonBottom SiofTrace.empty, Domain.VarNames.empty)
let at_least_nonbottom = Domain.join (NonBottom SiofTrace.bottom, Domain.VarNames.empty)
let exec_instr astate {ProcData.pdesc} _ (instr : Sil.instr) =
match instr with
@ -169,7 +169,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
then Some initialized_globals
else None )
in
Domain.join astate (NonBottom SiofTrace.empty, Domain.VarNames.of_list init)
Domain.join astate (NonBottom SiofTrace.bottom, Domain.VarNames.of_list init)
| 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
->
@ -228,7 +228,7 @@ let report_siof summary trace pdesc gname loc =
| Some (NonBottom summary, _) ->
summary
| _ ->
SiofTrace.empty
SiofTrace.bottom
in
let report_one_path ((_, path) as trace) =
let description =

@ -58,8 +58,6 @@ module type S = sig
; path_sink: Sink.t
; path_passthroughs: Passthroughs.t }
val empty : t
val sources : t -> Sources.t
(** get the sources of the trace. *)
@ -113,9 +111,6 @@ module type S = sig
val append : t -> t -> CallSite.t -> t
(** append the trace for given call site to the current caller trace *)
val is_empty : t -> bool
(** return true if this trace has no source or sink data *)
val pp : F.formatter -> t -> unit
val pp_path : Typ.Procname.t -> F.formatter -> path -> unit
@ -199,20 +194,20 @@ module Make (Spec : Spec) = struct
F.fprintf fmt " + Sanitizers(%a)" Sanitizers.pp sanitizers
in
if Known.is_empty known then
if Footprint.is_empty footprint then F.pp_print_string fmt "{}"
if Footprint.is_bottom footprint then F.pp_print_string fmt "{}"
else F.fprintf fmt "Footprint(%a)%a" Footprint.pp footprint pp_sanitizers sanitizers
else
F.fprintf fmt "%a + Footprint(%a)%a" Known.pp known Footprint.pp footprint pp_sanitizers
sanitizers
let empty = {known= Known.empty; footprint= Footprint.empty; sanitizers= Sanitizers.empty}
let empty = {known= Known.empty; footprint= Footprint.bottom; sanitizers= Sanitizers.empty}
(* note: empty known/footprint implies empty sanitizers *)
let is_empty {known; footprint} = Known.is_empty known && Footprint.BaseMap.is_empty footprint
let is_empty {known; footprint} = Known.is_empty known && Footprint.is_bottom footprint
let of_footprint access_path =
let footprint = Footprint.add_trace access_path true Footprint.empty in
let footprint = Footprint.add_trace access_path true Footprint.bottom in
{empty with footprint}
@ -276,7 +271,7 @@ module Make (Spec : Spec) = struct
let passthroughs t = t.passthroughs
let is_empty t =
let is_bottom t =
(* sources empty => sinks empty and passthroughs empty *)
Sources.is_empty t.sources
@ -497,7 +492,7 @@ module Make (Spec : Spec) = struct
(** compute caller_trace + callee_trace *)
let append caller_trace callee_trace callee_site =
if is_empty callee_trace then caller_trace
if is_bottom callee_trace then caller_trace
else
let sanitizers =
Sources.Sanitizers.join callee_trace.sources.sanitizers caller_trace.sources.sanitizers
@ -544,7 +539,7 @@ module Make (Spec : Spec) = struct
{sources; sinks; passthroughs}
let empty =
let bottom =
let sources = Sources.empty in
let sinks = Sinks.empty in
let passthroughs = Passthroughs.empty in

@ -23,6 +23,7 @@ end
module type S = sig
include Spec
(** bottom = this trace has no source or sink data *)
include AbstractDomain.WithBottom
module Sources : sig
@ -66,9 +67,6 @@ module type S = sig
; path_sink: Sink.t
; path_passthroughs: Passthroughs.t }
val empty : t
(** the empty trace *)
val sources : t -> Sources.t
(** get the sources of the trace. *)
@ -124,9 +122,6 @@ module type S = sig
val append : t -> t -> CallSite.t -> t
(** append the trace for given call site to the current caller trace *)
val is_empty : t -> bool
(** return true if this trace has no source or sink data *)
val pp : F.formatter -> t -> unit
val pp_path : Typ.Procname.t -> F.formatter -> path -> unit

@ -16,9 +16,9 @@ module Set = struct
let pp = APSet.pp
let empty = APSet.empty
let bottom = APSet.empty
let is_empty = APSet.is_empty
let is_bottom = APSet.is_empty
let normalize aps =
APSet.filter

@ -94,13 +94,13 @@ module Make (TraceDomain : AbstractDomain.WithBottom) (Config : Config) = struct
type t = node BaseMap.t
let empty = BaseMap.empty
let bottom = BaseMap.empty
let is_empty = BaseMap.is_empty
let is_bottom = BaseMap.is_empty
let make_node trace subtree = (trace, Subtree subtree)
let empty_node = make_node TraceDomain.empty AccessMap.empty
let empty_node = make_node TraceDomain.bottom AccessMap.empty
let is_empty_tree = function Star -> false | Subtree node_map -> AccessMap.is_empty node_map
@ -108,9 +108,9 @@ module Make (TraceDomain : AbstractDomain.WithBottom) (Config : Config) = struct
let make_starred_leaf trace = (trace, Star)
let empty_normal_leaf = make_normal_leaf TraceDomain.empty
let empty_normal_leaf = make_normal_leaf TraceDomain.bottom
let empty_starred_leaf = make_starred_leaf TraceDomain.empty
let empty_starred_leaf = make_starred_leaf TraceDomain.bottom
(* no need to make it tail-recursive, trees shouldn't be big enough to blow up the call stack *)
let rec node_depth (_, tree) = 1 + tree_depth tree
@ -420,7 +420,7 @@ module Make (TraceDomain : AbstractDomain.WithBottom) (Config : Config) = struct
| Star ->
F.pp_print_char fmt '*'
in
if not (TraceDomain.is_empty trace) then
if not (TraceDomain.is_bottom trace) then
if not (is_empty_tree subtree) then
F.fprintf fmt "(%a, %a)" TraceDomain.pp trace pp_subtree subtree
else TraceDomain.pp fmt trace

@ -134,7 +134,7 @@ let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
(* load the method's class *)
let init =
Typ.Procname.get_class_type_name proc_name
|> Option.fold ~init:ClassLoadsDomain.empty ~f:(load_class proc_desc tenv loc)
|> Option.fold ~init:ClassLoadsDomain.bottom ~f:(load_class proc_desc tenv loc)
in
let post = Procdesc.fold_instrs proc_desc ~init ~f:(exec_instr proc_desc tenv) in
report_loads proc_desc summary post ;

@ -16,7 +16,7 @@ let contains_global modified_params = ModifiedParamIndices.mem global modified_p
let pure = AbstractDomain.Types.Bottom
let is_pure = Domain.is_empty
let is_pure = Domain.is_bottom
let impure modified_args = AbstractDomain.Types.NonBottom modified_args

@ -576,7 +576,7 @@ let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
|> List.filter ~f:(fun (_, index) -> not (Int.equal 0 index))
|> List.fold ~init ~f:add_conditional_owned_formal
in
{RacerDDomain.empty with ownership; threads}
{RacerDDomain.bottom with ownership; threads}
else
(* add Owned(formal_index) predicates for each formal to indicate that each one is owned if
it is owned in the caller *)
@ -584,7 +584,7 @@ let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
List.fold ~init:own_locals ~f:add_conditional_owned_formal
(FormalMap.get_formals_indexes formal_map)
in
{RacerDDomain.empty with ownership; threads}
{RacerDDomain.bottom with ownership; threads}
in
match Analyzer.compute_post proc_data ~initial with
| Some {threads; locks; accesses; ownership; attribute_map} ->
@ -730,9 +730,9 @@ let trace_of_pname orig_sink orig_pdesc callee_pname =
if Access.matches ~caller:orig_access ~callee:(PathDomain.Sink.kind snapshot.access) then
PathDomain.add_sink snapshot.access acc
else acc )
accesses PathDomain.empty
accesses PathDomain.bottom
| _ ->
PathDomain.empty
PathDomain.bottom
let make_trace ~report_kind original_path pdesc =

@ -178,7 +178,7 @@ module LocksDomain = struct
not (is_empty astate)
let lookup_count lock astate = try find lock astate with Caml.Not_found -> LockCount.empty
let lookup_count lock astate = find_opt lock astate |> Option.value ~default:LockCount.bottom
let acquire_lock astate =
let count = lookup_count the_only_lock astate in
@ -189,7 +189,7 @@ module LocksDomain = struct
let count = lookup_count the_only_lock astate in
try
let count' = LockCount.decrement count in
if LockCount.is_empty count' then remove the_only_lock astate
if LockCount.is_bottom count' then remove the_only_lock astate
else add the_only_lock count' astate
with Caml.Not_found -> astate
@ -198,13 +198,13 @@ module LocksDomain = struct
let caller_count = lookup_count the_only_lock caller_astate in
let callee_count = lookup_count the_only_lock callee_astate in
let sum = LockCount.add caller_count callee_count in
if LockCount.is_empty sum then caller_astate else add the_only_lock sum caller_astate
if LockCount.is_bottom sum then caller_astate else add the_only_lock sum caller_astate
end
module ThreadsDomain = struct
type t = NoThread | AnyThreadButSelf | AnyThread [@@deriving compare]
let empty = NoThread
let bottom = NoThread
(* NoThread < AnyThreadButSelf < Any *)
let ( <= ) ~lhs ~rhs =
@ -253,7 +253,7 @@ module ThreadsDomain = struct
match join astate1 astate2 with AnyThread -> true | NoThread | AnyThreadButSelf -> false
let is_empty = function NoThread -> true | _ -> false
let is_bottom = function NoThread -> true | _ -> false
let is_any_but_self = function AnyThreadButSelf -> true | _ -> false
@ -516,8 +516,8 @@ type t =
; ownership: OwnershipDomain.t
; attribute_map: AttributeMapDomain.t }
let empty =
let threads = ThreadsDomain.empty in
let bottom =
let threads = ThreadsDomain.bottom in
let locks = LocksDomain.empty in
let accesses = AccessDomain.empty in
let ownership = OwnershipDomain.empty in
@ -525,8 +525,8 @@ let empty =
{threads; locks; accesses; ownership; attribute_map}
let is_empty {threads; locks; accesses; ownership; attribute_map} =
ThreadsDomain.is_empty threads && LocksDomain.is_empty locks && AccessDomain.is_empty accesses
let is_bottom {threads; locks; accesses; ownership; attribute_map} =
ThreadsDomain.is_bottom threads && LocksDomain.is_empty locks && AccessDomain.is_empty accesses
&& OwnershipDomain.is_empty ownership
&& AttributeMapDomain.is_empty attribute_map
@ -572,7 +572,7 @@ type summary =
; return_attributes: AttributeSetDomain.t }
let empty_summary =
{ threads= ThreadsDomain.empty
{ threads= ThreadsDomain.bottom
; locks= LocksDomain.empty
; accesses= AccessDomain.empty
; return_ownership= OwnershipAbstractValue.unowned

@ -146,7 +146,7 @@ let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
let proc_data = ProcData.make proc_desc tenv formals in
let loc = Procdesc.get_loc proc_desc in
let initial =
if not (Procdesc.is_java_synchronized proc_desc) then StarvationDomain.empty
if not (Procdesc.is_java_synchronized proc_desc) then StarvationDomain.bottom
else
let lock =
match pname with
@ -157,7 +157,7 @@ let analyze_procedure {Callbacks.proc_desc; tenv; summary} =
| _ ->
FormalMap.get_formal_base 0 formals |> Option.map ~f:(fun base -> (base, []))
in
StarvationDomain.acquire tenv StarvationDomain.empty loc (Option.to_list lock)
StarvationDomain.acquire tenv StarvationDomain.bottom loc (Option.to_list lock)
in
let initial =
ConcurrencyModels.runs_on_ui_thread ~attrs_of_pname:Summary.proc_resolve_attributes tenv
@ -399,7 +399,7 @@ let report_deadlocks env {StarvationDomain.order; ui} report_map' =
(* for each summary related to the endpoint, analyse and report on its pairs *)
fold_reportable_summaries env endpoint_class ~init:report_map
~f:(fun acc (endpoint_pname, {order= endp_order; ui= endp_ui}) ->
if UIThreadDomain.is_empty ui || UIThreadDomain.is_empty endp_ui then
if UIThreadDomain.is_bottom ui || UIThreadDomain.is_bottom endp_ui then
OrderDomain.fold (report_endpoint_elem elem endpoint_pname) endp_order acc
else acc ) )
in
@ -471,7 +471,7 @@ let report_starvation env {StarvationDomain.events; ui} report_map' =
fold_reportable_summaries env endpoint_class ~init:report_map
~f:(fun acc (endpoint_pname, {order; ui}) ->
(* skip methods on ui thread, as they cannot run in parallel to us *)
if UIThreadDomain.is_empty ui then
if UIThreadDomain.is_bottom ui then
OrderDomain.fold
(report_remote_block ui_explain event endpoint_lock endpoint_pname)
order acc

@ -247,17 +247,17 @@ type t =
; order: OrderDomain.t
; ui: UIThreadDomain.t }
let empty =
let bottom =
{ events= EventDomain.empty
; guard_map= GuardToLockMap.empty
; lock_state= LockState.empty
; order= OrderDomain.empty
; ui= UIThreadDomain.empty }
; ui= UIThreadDomain.bottom }
let is_empty {events; guard_map; lock_state; order; ui} =
let is_bottom {events; guard_map; lock_state; order; ui} =
EventDomain.is_empty events && GuardToLockMap.is_empty guard_map && OrderDomain.is_empty order
&& LockState.is_empty lock_state && UIThreadDomain.is_empty ui
&& LockState.is_empty lock_state && UIThreadDomain.is_bottom ui
let pp fmt {events; guard_map; lock_state; order; ui} =

@ -59,7 +59,7 @@ end
module OrderDomain : ExplicitTrace.FiniteSet with type elt = Order.t
module LockState : AbstractDomain.WithBottom
module LockState : AbstractDomain.WithTop
module UIThreadExplanationDomain : sig
include ExplicitTrace.TraceElem with type elem_t = string
@ -71,7 +71,7 @@ module UIThreadDomain :
AbstractDomain.WithBottom
with type t = UIThreadExplanationDomain.t AbstractDomain.Types.bottom_lifted
module GuardToLockMap : AbstractDomain.WithBottom
module GuardToLockMap : AbstractDomain.WithTop
type t =
{ events: EventDomain.t

@ -58,7 +58,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
| Some (trace, _) ->
trace
| None ->
TraceDomain.empty
TraceDomain.bottom
let exp_get_node_ ~abstracted raw_access_path access_tree proc_data =
@ -130,13 +130,13 @@ module Make (TaintSpecification : TaintSpec.S) = struct
let get_summary pname =
if Typ.Procname.equal pname (Procdesc.get_proc_name proc_data.pdesc) then
(* read_summary will trigger ondemand analysis of the current proc. we don't want that. *)
TaintDomain.empty
TaintDomain.bottom
else
match Payload.read proc_data.pdesc pname with
| Some summary ->
TaintSpecification.of_summary_access_tree summary
| None ->
TaintDomain.empty
TaintDomain.bottom
in
let get_caller_string caller_site =
let caller_pname = CallSite.pname caller_site in
@ -333,7 +333,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
match HilExp.ignore_cast exp with
| HilExp.AccessExpression actual_ae_raw
when not
(TraceDomain.Sources.Footprint.is_empty
(TraceDomain.Sources.Footprint.is_bottom
(TraceDomain.sources actual_trace').footprint) ->
let actual_ap =
AccessPath.Abs.Abstracted
@ -427,7 +427,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
in
let trace = instantiate_and_report callee_trace caller_trace access_tree_acc in
let pruned_trace =
if TraceDomain.Sources.Footprint.is_empty (TraceDomain.sources trace).footprint then
if TraceDomain.Sources.Footprint.is_bottom (TraceDomain.sources trace).footprint then
(* empty footprint; nothing else can flow into these sinks. so don't track them *)
TraceDomain.update_sinks trace TraceDomain.Sinks.empty
else trace
@ -552,14 +552,14 @@ module Make (TaintSpecification : TaintSpec.S) = struct
~f:should_taint_typ
then TraceDomain.Sources.Footprint.add_trace access_path true acc
else acc )
sources.footprint TraceDomain.Sources.Footprint.empty
sources.footprint TraceDomain.Sources.Footprint.bottom
in
let filtered_sources = {sources with footprint= filtered_footprint} in
if TraceDomain.Sources.is_empty filtered_sources then access_tree
else
let trace' = TraceDomain.update_sources trace_with_propagation filtered_sources in
let pruned_trace =
if TraceDomain.Sources.Footprint.is_empty filtered_footprint then
if TraceDomain.Sources.Footprint.is_bottom filtered_footprint then
(* empty footprint; nothing else can flow into these sinks. so don't track them *)
TraceDomain.update_sinks trace' TraceDomain.Sinks.empty
else trace'
@ -742,7 +742,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
let passthroughs = passthroughs trace in
let sinks = sinks trace in
(* invariant 1: sinks with no footprint sources are dead and should be forgotten *)
if Sources.Footprint.is_empty footprint_sources && not (Sinks.is_empty sinks) then
if Sources.Footprint.is_bottom footprint_sources && not (Sinks.is_empty sinks) then
Logging.die InternalError
"Trace %a associated with %a tracks sinks even though no more sources can flow into \
them"
@ -807,7 +807,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
directly with a formal. In Java this can't happen, so we only care if the formal flows to
a sink *)
( if is_java then TraceDomain.Sinks.is_empty (TraceDomain.sinks trace)
else TraceDomain.is_empty trace )
else TraceDomain.is_bottom trace )
&&
match tree with
| TaintDomain.Subtree subtree ->
@ -827,7 +827,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
else
let node' =
if TraceDomain.Sinks.is_empty (TraceDomain.sinks trace) then
(TraceDomain.empty, subtree)
(TraceDomain.bottom, subtree)
else node
in
AccessPath.BaseMap.add base node' acc
@ -844,7 +844,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
| None ->
(* base is a local var *)
acc )
access_tree' TaintDomain.empty
access_tree' TaintDomain.bottom
in
if Config.developer_mode then check_invariants with_footprint_vars ;
TaintSpecification.to_summary_access_tree with_footprint_vars
@ -864,7 +864,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct
TaintDomain.add_trace base_ap (TraceDomain.of_source source) acc
| None ->
acc )
~init:TaintDomain.empty
~init:TaintDomain.bottom
(TraceDomain.Source.get_tainted_formals pdesc tenv)
in
let initial = make_initial proc_desc in

@ -89,7 +89,7 @@ let tests =
(* flatten access tree into list of access paths with associated traces *)
let trace_assocs =
MockTaintAnalysis.TaintDomain.trace_fold
(fun acc ap t -> if not (MockTrace.is_empty t) then (ap, t) :: acc else acc)
(fun acc ap t -> if not (MockTrace.is_bottom t) then (ap, t) :: acc else acc)
(fst astate) []
in
PrettyPrintable.pp_collection ~pp_item fmt (List.rev trace_assocs)
@ -157,6 +157,6 @@ let tests =
, [assign_to_non_source "ret_id"; call_sink "ret_id"; assert_empty] ) ]
|> TestInterpreter.create_tests ~pp_opt:pp_sparse
{formal_map= FormalMap.empty; summary= Summary.dummy}
~initial:(MockTaintAnalysis.Domain.empty, Bindings.empty)
~initial:(MockTaintAnalysis.Domain.bottom, Bindings.empty)
in
"taint_test_suite" >::: test_list

@ -229,7 +229,7 @@ let tests =
|> Domain.BaseMap.singleton x_base
in
Domain.assert_trees_equal
(Domain.add_trace xF_star added_trace Domain.empty)
(Domain.add_trace xF_star added_trace Domain.bottom)
xF_star_tree_added_trace ;
(* add starred path when base present *)
Domain.assert_trees_equal
@ -421,7 +421,7 @@ let tests =
in
let depth_test =
let depth_test_ _ =
assert_equal (Domain.depth Domain.empty) 0 ;
assert_equal (Domain.depth Domain.bottom) 0 ;
assert_equal (Domain.depth x_base_tree) 1 ;
assert_equal (Domain.depth x_y_base_tree) 1 ;
assert_equal (Domain.depth xFG_tree) 3 ;
@ -445,13 +445,13 @@ let tests =
let x_tree = Max1.BaseMap.singleton x_base (Max1.make_normal_leaf x_trace) in
let x_star_tree = Max1.BaseMap.singleton x_base (Max1.make_starred_leaf x_trace) in
(* adding (x.f, "x") to a tree with max height 1 should yield x |-> ("x", * ) *)
Max1.assert_trees_equal (Max1.add_trace xF x_trace Max1.empty) x_star_tree ;
Max1.assert_trees_equal (Max1.add_trace xF x_trace Max1.bottom) x_star_tree ;
(* same, but with (x.f.g, "x") *)
Max1.assert_trees_equal (Max1.add_trace xFG x_trace Max1.empty) x_star_tree ;
Max1.assert_trees_equal (Max1.add_trace xFG x_trace Max1.bottom) x_star_tree ;
(* adding node (f, "x") via access path x should also yield the same tree *)
Max1.assert_trees_equal (Max1.add_node x f_node Max1.empty) x_star_tree ;
Max1.assert_trees_equal (Max1.add_node x f_node Max1.bottom) x_star_tree ;
(* adding (x, "x") shouldn't add stars *)
Max1.assert_trees_equal (Max1.add_trace x x_trace Max1.empty) x_tree ;
Max1.assert_trees_equal (Max1.add_trace x x_trace Max1.bottom) x_tree ;
let module Max2 = MakeTree (struct
let max_depth = 2
@ -474,9 +474,9 @@ let tests =
let xF_tree = Max2.BaseMap.singleton x_base f_node in
let xF_star_tree = Max2.BaseMap.singleton x_base f_star_node in
(* adding x.f to an empty tree should't add stars... *)
Max2.assert_trees_equal (Max2.add_trace xF x_trace Max2.empty) xF_tree ;
Max2.assert_trees_equal (Max2.add_trace xF x_trace Max2.bottom) xF_tree ;
(* ... but adding x.f.g should *)
Max2.assert_trees_equal (Max2.add_trace xFG x_trace Max2.empty) xF_star_tree ;
Max2.assert_trees_equal (Max2.add_trace xFG x_trace Max2.bottom) xF_star_tree ;
(* adding the node (f.g, "x") to a tree with x should produce the same result *)
Max2.assert_trees_equal (Max2.add_node x fG_node x_tree) xF_star_tree
in
@ -505,7 +505,7 @@ let tests =
let xG_tree = Max1.BaseMap.singleton x_base g_node in
let x_star_tree = Max1.BaseMap.singleton x_base star_node in
(* adding x.f to a tree containing just x should work *)
Max1.assert_trees_equal (Max1.add_trace xF y_trace Max1.empty) xF_tree ;
Max1.assert_trees_equal (Max1.add_trace xF y_trace Max1.bottom) xF_tree ;
(* but adding x.g to a tree containing x.f should create a star *)
Max1.assert_trees_equal (Max1.add_trace xG z_trace xF_tree) x_star_tree ;
(* joining the x.f and x.g trees should also create a star *)

Loading…
Cancel
Save