[inferbo] Simplify stack/heap memory domain

Summary:
In SIL, (1) some program variables (e.g., array parameter) are used as pointers to heap addresses and (2) the other program variables (e.g., local array) are used as addresses themselves.  So, the values of (1) are retrieved by the `Load` command, while that of (2) are by `Exp.Lvar` expressions directly.

To address them differently, we had managed two maps (`Mem.Stack` and `Mem.Heap`), but which introduced function duplications on abstract memory and increased complexity.  This diff merges the two maps, and instead a location set is used for distinguishing two types of abstract locations during analysis.

Reviewed By: mbouaziz

Differential Revision: D9420388

fbshipit-source-id: 13f824850
master
Sungkeun Cho 6 years ago committed by Facebook Github Bot
parent 49e582fa49
commit 1bf8ed95b8

@ -37,7 +37,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let instantiate_ret ret callee_pname ~callee_exit_mem subst_map mem ret_alias location = let instantiate_ret ret callee_pname ~callee_exit_mem subst_map mem ret_alias location =
let copy_reachable_new_locs_from locs mem = let copy_reachable_new_locs_from locs mem =
let copy loc acc = let copy loc acc =
Option.value_map (Dom.Mem.find_heap_opt loc callee_exit_mem) ~default:acc ~f:(fun v -> Option.value_map (Dom.Mem.find_opt loc callee_exit_mem) ~default:acc ~f:(fun v ->
let v = let v =
Dom.Val.subst v subst_map location |> Dom.Val.add_trace_elem (Trace.Return location) Dom.Val.subst v subst_map location |> Dom.Val.add_trace_elem (Trace.Return location)
in in
@ -48,7 +48,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
in in
let id = fst ret in let id = fst ret in
let ret_loc = Loc.of_pvar (Pvar.get_ret_pvar callee_pname) in let ret_loc = Loc.of_pvar (Pvar.get_ret_pvar callee_pname) in
let ret_val = Dom.Mem.find_heap ret_loc callee_exit_mem in let ret_val = Dom.Mem.find ret_loc callee_exit_mem in
let ret_var = Loc.of_var (Var.of_id id) in let ret_var = Loc.of_var (Var.of_id id) in
let add_ret_alias l = Dom.Mem.load_alias id l mem in let add_ret_alias l = Dom.Mem.load_alias id l mem in
let mem = Option.value_map ret_alias ~default:mem ~f:add_ret_alias in let mem = Option.value_map ret_alias ~default:mem ~f:add_ret_alias in
@ -68,28 +68,27 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
match Tenv.lookup tenv typename with match Tenv.lookup tenv typename with
| Some str -> | Some str ->
let formal_locs = let formal_locs =
Dom.Mem.find_heap (Loc.of_pvar (fst formal)) callee_exit_mem Dom.Mem.find (Loc.of_pvar (fst formal)) callee_exit_mem |> Dom.Val.get_array_blk
|> Dom.Val.get_array_blk |> ArrayBlk.get_pow_loc |> ArrayBlk.get_pow_loc
in in
let instantiate_fld mem (fn, _, _) = let instantiate_fld mem (fn, _, _) =
let formal_fields = PowLoc.append_field formal_locs ~fn in let formal_fields = PowLoc.append_field formal_locs ~fn in
let v = Dom.Mem.find_heap_set formal_fields callee_exit_mem in let v = Dom.Mem.find_set formal_fields callee_exit_mem in
let actual_fields = PowLoc.append_field (Dom.Val.get_all_locs actual) ~fn in let actual_fields = PowLoc.append_field (Dom.Val.get_all_locs actual) ~fn in
Dom.Val.subst v subst_map location Dom.Val.subst v subst_map location
|> Fn.flip (Dom.Mem.strong_update_heap actual_fields) mem |> Fn.flip (Dom.Mem.strong_update actual_fields) mem
in in
List.fold ~f:instantiate_fld ~init:mem str.Typ.Struct.fields List.fold ~f:instantiate_fld ~init:mem str.Typ.Struct.fields
| _ -> | _ ->
mem ) mem )
| _ -> | _ ->
let formal_locs = let formal_locs =
Dom.Mem.find_heap (Loc.of_pvar (fst formal)) callee_exit_mem |> Dom.Val.get_array_blk Dom.Mem.find (Loc.of_pvar (fst formal)) callee_exit_mem |> Dom.Val.get_array_blk
|> ArrayBlk.get_pow_loc |> ArrayBlk.get_pow_loc
in in
let v = Dom.Mem.find_heap_set formal_locs callee_exit_mem in let v = Dom.Mem.find_set formal_locs callee_exit_mem in
let actual_locs = Dom.Val.get_all_locs actual in let actual_locs = Dom.Val.get_all_locs actual in
Dom.Val.subst v subst_map location Dom.Val.subst v subst_map location |> Fn.flip (Dom.Mem.strong_update actual_locs) mem )
|> Fn.flip (Dom.Mem.strong_update_heap actual_locs) mem )
| _ -> | _ ->
mem mem
in in
@ -159,7 +158,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| "__inferbo_empty" when Loc.is_return loc_v -> ( | "__inferbo_empty" when Loc.is_return loc_v -> (
match Sem.get_formals pdesc with match Sem.get_formals pdesc with
| [(formal, _)] -> | [(formal, _)] ->
let formal_v = Dom.Mem.find_heap (Loc.of_pvar formal) mem in let formal_v = Dom.Mem.find (Loc.of_pvar formal) mem in
Dom.Mem.store_empty_alias formal_v loc_v exp2 mem Dom.Mem.store_empty_alias formal_v loc_v exp2 mem
| _ -> | _ ->
assert false ) assert false )
@ -171,7 +170,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
mem mem
| Prune (exp, _, _, _) -> | Prune (exp, _, _, _) ->
Sem.Prune.prune exp mem Sem.Prune.prune exp mem
| Call (((id, _) as ret), Const (Cfun callee_pname), params, location, _) -> ( | Call (((id, _) as ret), Const (Cfun callee_pname), params, location, _)
-> (
let mem = Dom.Mem.add_stack_loc (Loc.of_id id) mem in
match Models.Call.dispatch tenv callee_pname params with match Models.Call.dispatch tenv callee_pname params with
| Some {Models.exec} -> | Some {Models.exec} ->
let node_hash = CFG.Node.hash node in let node_hash = CFG.Node.hash node in
@ -198,6 +199,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
location ; location ;
Dom.Mem.add_unknown_from id ~callee_pname ~location mem ) Dom.Mem.add_unknown_from id ~callee_pname ~location mem )
| Call ((id, _), fun_exp, _, location, _) -> | Call ((id, _), fun_exp, _, location, _) ->
let mem = Dom.Mem.add_stack_loc (Loc.of_id id) mem in
let () = let () =
L.(debug BufferOverrun Verbose) L.(debug BufferOverrun Verbose)
"/!\\ Call to non-const function %a at %a" Exp.pp fun_exp Location.pp location "/!\\ Call to non-const function %a at %a" Exp.pp fun_exp Location.pp location

@ -132,6 +132,8 @@ module Val = struct
let of_int n = of_itv (Itv.of_int n) let of_int n = of_itv (Itv.of_int n)
let of_loc : Loc.t -> t = fun x -> {bot with powloc= PowLoc.singleton x}
let of_pow_loc : PowLoc.t -> t = fun x -> {bot with powloc= x} let of_pow_loc : PowLoc.t -> t = fun x -> {bot with powloc= x}
let of_array_alloc : Allocsite.t -> stride:int option -> offset:Itv.t -> size:Itv.t -> t = let of_array_alloc : Allocsite.t -> stride:int option -> offset:Itv.t -> size:Itv.t -> t =
@ -308,64 +310,17 @@ module Val = struct
end end
end end
module Stack = struct module StackLocs = struct
include AbstractDomain.Map (Loc) (Val) include AbstractDomain.FiniteSet (Loc)
let bot = empty let bot = empty
let find : Loc.t -> astate -> Val.t = fun l m -> try find l m with Caml.Not_found -> Val.bot
let find_set : PowLoc.t -> astate -> Val.t =
fun locs mem ->
let find_join loc acc = Val.join acc (find loc mem) in
PowLoc.fold find_join locs Val.bot
let remove_temps : Ident.t list -> astate -> astate =
fun temps mem ->
let remove_temp mem temp =
let temp_loc = Loc.of_id temp in
remove temp_loc mem
in
List.fold temps ~init:mem ~f:remove_temp
end end
module Heap = struct module MemPure = struct
include AbstractDomain.Map (Loc) (Val) include AbstractDomain.Map (Loc) (Val)
let bot = empty let bot = empty
let find : Loc.t -> astate -> Val.t =
fun l m -> try find l m with Caml.Not_found -> Val.Itv.top
let find_set : PowLoc.t -> astate -> Val.t =
fun locs mem ->
let find_join loc acc = Val.join acc (find loc mem) in
PowLoc.fold find_join locs Val.bot
let transform : f:(Val.t -> Val.t) -> PowLoc.t -> astate -> astate =
fun ~f locs mem -> PowLoc.fold (fun loc -> find loc mem |> f |> add loc) locs mem
let add x v =
let sym = if Itv.is_empty (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)
in
add x {v with Val.sym; Val.offset_sym; Val.size_sym}
let strong_update : PowLoc.t -> Val.t -> astate -> astate =
fun locs v mem -> PowLoc.fold (fun x -> add x v) locs mem
let weak_update : PowLoc.t -> Val.t -> astate -> astate =
fun locs v mem -> PowLoc.fold (fun x -> add x (Val.join v (find x mem))) locs mem
let get_return : astate -> Val.t = let get_return : astate -> Val.t =
fun mem -> fun mem ->
let mem = filter (fun l _ -> Loc.is_return l) mem in let mem = filter (fun l _ -> Loc.is_return l) mem in
@ -464,10 +419,7 @@ module AliasMap = struct
let find : Ident.t -> t -> AliasTarget.t option = fun k m -> M.find_opt k m let find : Ident.t -> t -> AliasTarget.t option = fun k m -> M.find_opt k m
let remove_temps : Ident.t list -> t -> t = let remove : Ident.t -> t -> t = M.remove
fun temps m ->
let remove_temp m temp = M.remove temp m in
List.fold temps ~init:m ~f:remove_temp
end end
module AliasRet = struct module AliasRet = struct
@ -554,8 +506,8 @@ module Alias = struct
else a else a
let remove_temps : Ident.t list -> astate -> astate = let remove_temp : Ident.t -> astate -> astate =
fun temps a -> (AliasMap.remove_temps temps (fst a), snd a) fun temp (alias_map, alias_ret) -> (AliasMap.remove temp alias_map, alias_ret)
let pp : F.formatter -> astate -> unit = let pp : F.formatter -> astate -> unit =
@ -647,8 +599,8 @@ end
module MemReach = struct module MemReach = struct
type astate = type astate =
{ stack: Stack.astate { stack_locs: StackLocs.astate
; heap: Heap.astate ; mem_pure: MemPure.astate
; alias: Alias.astate ; alias: Alias.astate
; latest_prune: LatestPrune.astate ; latest_prune: LatestPrune.astate
; relation: Relation.astate } ; relation: Relation.astate }
@ -656,8 +608,8 @@ module MemReach = struct
type t = astate type t = astate
let init : t = let init : t =
{ stack= Stack.bot { stack_locs= StackLocs.bot
; heap= Heap.bot ; mem_pure= MemPure.bot
; alias= Alias.bot ; alias= Alias.bot
; latest_prune= LatestPrune.top ; latest_prune= LatestPrune.top
; relation= Relation.empty } ; relation= Relation.empty }
@ -666,7 +618,8 @@ module MemReach = struct
let ( <= ) ~lhs ~rhs = let ( <= ) ~lhs ~rhs =
if phys_equal lhs rhs then true if phys_equal lhs rhs then true
else else
Stack.( <= ) ~lhs:lhs.stack ~rhs:rhs.stack && Heap.( <= ) ~lhs:lhs.heap ~rhs:rhs.heap StackLocs.( <= ) ~lhs:lhs.stack_locs ~rhs:rhs.stack_locs
&& MemPure.( <= ) ~lhs:lhs.mem_pure ~rhs:rhs.mem_pure
&& Alias.( <= ) ~lhs:lhs.alias ~rhs:rhs.alias && Alias.( <= ) ~lhs:lhs.alias ~rhs:rhs.alias
&& LatestPrune.( <= ) ~lhs:lhs.latest_prune ~rhs:rhs.latest_prune && LatestPrune.( <= ) ~lhs:lhs.latest_prune ~rhs:rhs.latest_prune
&& Relation.( <= ) ~lhs:lhs.relation ~rhs:rhs.relation && Relation.( <= ) ~lhs:lhs.relation ~rhs:rhs.relation
@ -675,8 +628,8 @@ module MemReach = struct
let widen ~prev ~next ~num_iters = let widen ~prev ~next ~num_iters =
if phys_equal prev next then prev if phys_equal prev next then prev
else else
{ stack= Stack.widen ~prev:prev.stack ~next:next.stack ~num_iters { stack_locs= StackLocs.widen ~prev:prev.stack_locs ~next:next.stack_locs ~num_iters
; heap= Heap.widen ~prev:prev.heap ~next:next.heap ~num_iters ; mem_pure= MemPure.widen ~prev:prev.mem_pure ~next:next.mem_pure ~num_iters
; alias= Alias.widen ~prev:prev.alias ~next:next.alias ~num_iters ; alias= Alias.widen ~prev:prev.alias ~next:next.alias ~num_iters
; latest_prune= LatestPrune.widen ~prev:prev.latest_prune ~next:next.latest_prune ~num_iters ; latest_prune= LatestPrune.widen ~prev:prev.latest_prune ~next:next.latest_prune ~num_iters
; relation= Relation.widen ~prev:prev.relation ~next:next.relation ~num_iters } ; relation= Relation.widen ~prev:prev.relation ~next:next.relation ~num_iters }
@ -684,8 +637,8 @@ module MemReach = struct
let join : t -> t -> t = let join : t -> t -> t =
fun x y -> fun x y ->
{ stack= Stack.join x.stack y.stack { stack_locs= StackLocs.join x.stack_locs y.stack_locs
; heap= Heap.join x.heap y.heap ; mem_pure= MemPure.join x.mem_pure y.mem_pure
; alias= Alias.join x.alias y.alias ; alias= Alias.join x.alias y.alias
; latest_prune= LatestPrune.join x.latest_prune y.latest_prune ; latest_prune= LatestPrune.join x.latest_prune y.latest_prune
; relation= Relation.join x.relation y.relation } ; relation= Relation.join x.relation y.relation }
@ -693,23 +646,28 @@ module MemReach = struct
let pp : F.formatter -> t -> unit = let pp : F.formatter -> t -> unit =
fun fmt x -> fun fmt x ->
F.fprintf fmt "Stack:@;%a@;Heap:@;%a@;%a" Stack.pp x.stack Heap.pp x.heap Alias.pp x.alias ; F.fprintf fmt "Stack:@;%a@;Heap:@;%a@;%a" StackLocs.pp x.stack_locs MemPure.pp x.mem_pure
Alias.pp x.alias ;
if Option.is_some Config.bo_relational_domain then if Option.is_some Config.bo_relational_domain then
F.fprintf fmt "@;Relation:@;%a" Relation.pp x.relation F.fprintf fmt "@;Relation:@;%a" Relation.pp x.relation
let find_stack : Loc.t -> t -> Val.t = fun k m -> Stack.find k m.stack let is_stack_loc : Loc.t -> t -> bool = fun l m -> StackLocs.mem l m.stack_locs
let find_stack_set : PowLoc.t -> t -> Val.t = fun k m -> Stack.find_set k m.stack let find_opt : Loc.t -> t -> Val.t option = fun l m -> MemPure.find_opt l m.mem_pure
let find_heap : Loc.t -> t -> Val.t = fun k m -> Heap.find k m.heap let find_stack : Loc.t -> t -> Val.t = fun l m -> Option.value (find_opt l m) ~default:Val.bot
let find_heap_opt : Loc.t -> t -> Val.t option = fun k m -> Heap.find_opt k m.heap let find_heap : Loc.t -> t -> Val.t = fun l m -> Option.value (find_opt l m) ~default:Val.Itv.top
let find : Loc.t -> t -> Val.t =
fun l m -> if is_stack_loc l m then find_stack l m else find_heap l m
let find_heap_set : PowLoc.t -> t -> Val.t = fun k m -> Heap.find_set k m.heap
let find_set : PowLoc.t -> t -> Val.t = let find_set : PowLoc.t -> t -> Val.t =
fun k m -> Val.join (find_stack_set k m) (find_heap_set k m) fun locs m ->
let find_join loc acc = Val.join acc (find loc m) in
PowLoc.fold find_join locs Val.bot
let find_alias : Ident.t -> t -> AliasTarget.t option = fun k m -> Alias.find k m.alias let find_alias : Ident.t -> t -> AliasTarget.t option = fun k m -> Alias.find k m.alias
@ -737,9 +695,29 @@ module MemReach = struct
fun formal loc e m -> {m with alias= Alias.store_empty formal loc e m.alias} fun formal loc e m -> {m with alias= Alias.store_empty formal loc e m.alias}
let add_stack : Loc.t -> Val.t -> t -> t = fun k v m -> {m with stack= Stack.add k v m.stack} let add_stack_loc : Loc.t -> t -> t = fun k m -> {m with stack_locs= StackLocs.add k m.stack_locs}
let add_stack : Loc.t -> Val.t -> t -> t =
fun k v m ->
{m with stack_locs= StackLocs.add k m.stack_locs; mem_pure= MemPure.add k v m.mem_pure}
let replace_stack : Loc.t -> Val.t -> t -> t =
fun k v m -> {m with mem_pure= MemPure.add k v m.mem_pure}
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 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)
in
{v with Val.sym; Val.offset_sym; Val.size_sym}
in
{m with mem_pure= MemPure.add x v m.mem_pure}
let add_heap : Loc.t -> Val.t -> t -> t = fun k v m -> {m with heap= Heap.add k v m.heap}
let add_unknown_from let add_unknown_from
: Ident.t -> callee_pname:Typ.Procname.t option -> location:Location.t -> t -> t = : Ident.t -> callee_pname:Typ.Procname.t option -> location:Location.t -> t -> t =
@ -748,37 +726,48 @@ module MemReach = struct
add_stack (Loc.of_id id) val_unknown m |> add_heap Loc.unknown val_unknown add_stack (Loc.of_id id) val_unknown m |> add_heap Loc.unknown val_unknown
let strong_update_heap : PowLoc.t -> Val.t -> t -> t = let strong_update : PowLoc.t -> Val.t -> t -> t =
fun p v m -> {m with heap= Heap.strong_update p v m.heap} fun locs v m ->
let strong_update1 l m = if is_stack_loc l m then replace_stack l v m else add_heap l v m in
PowLoc.fold strong_update1 locs m
let transform_heap : f:(Val.t -> Val.t) -> PowLoc.t -> t -> t = let transform_mem : f:(Val.t -> Val.t) -> PowLoc.t -> t -> t =
fun ~f p m -> {m with heap= Heap.transform ~f p m.heap} fun ~f locs m ->
let transform_mem1 l m =
let add, find =
if is_stack_loc l m then (replace_stack, find_stack) else (add_heap, find_heap)
in
add l (f (find l m)) m
in
PowLoc.fold transform_mem1 locs m
let weak_update_heap : PowLoc.t -> Val.t -> t -> t =
fun p v m -> {m with heap= Heap.weak_update p v m.heap}
let weak_update locs v m = transform_mem ~f:(fun v' -> Val.join v' v) locs m
let get_return : t -> Val.t = fun m -> Heap.get_return m.heap let get_return : t -> Val.t = fun m -> MemPure.get_return m.mem_pure
let update_mem : PowLoc.t -> Val.t -> t -> t = let update_mem : PowLoc.t -> Val.t -> t -> t =
fun ploc v s -> fun ploc v s ->
if can_strong_update ploc then strong_update_heap ploc v s if can_strong_update ploc then strong_update ploc v s
else else
let () = let () =
L.(debug BufferOverrun Verbose) "Weak update for %a <- %a@." PowLoc.pp ploc Val.pp v L.(debug BufferOverrun Verbose) "Weak update for %a <- %a@." PowLoc.pp ploc Val.pp v
in in
weak_update_heap ploc v s weak_update ploc v s
let transform_mem : f:(Val.t -> Val.t) -> PowLoc.t -> t -> t = let remove_temp : Ident.t -> t -> t =
fun ~f ploc s -> transform_heap ~f ploc s fun temp m ->
let l = Loc.of_id temp in
{ m with
stack_locs= StackLocs.remove l m.stack_locs
; mem_pure= MemPure.remove l m.mem_pure
; alias= Alias.remove_temp temp m.alias }
let remove_temps : Ident.t list -> t -> t = let remove_temps : Ident.t list -> t -> t =
fun temps m -> fun temps m -> List.fold temps ~init:m ~f:(fun acc temp -> remove_temp temp acc)
{m with stack= Stack.remove_temps temps m.stack; alias= Alias.remove_temps temps m.alias}
let set_prune_pairs : PrunePairs.t -> t -> t = let set_prune_pairs : PrunePairs.t -> t -> t =
@ -820,14 +809,14 @@ module MemReach = struct
and add_from_loc heap loc acc = and add_from_loc heap loc acc =
if PowLoc.mem loc acc then acc if PowLoc.mem loc acc then acc
else else
let reachable_locs = Heap.fold (add_reachable1 ~root:loc) heap PowLoc.empty in let reachable_locs = MemPure.fold (add_reachable1 ~root:loc) heap PowLoc.empty in
add_from_locs heap reachable_locs (PowLoc.add loc acc) add_from_locs heap reachable_locs (PowLoc.add loc acc)
in in
fun locs m -> add_from_locs m.heap locs PowLoc.empty fun locs m -> add_from_locs m.mem_pure locs PowLoc.empty
let heap_range : filter_loc:(Loc.t -> bool) -> t -> Itv.NonNegativePolynomial.astate = let range : filter_loc:(Loc.t -> bool) -> t -> Itv.NonNegativePolynomial.astate =
fun ~filter_loc {heap} -> Heap.range ~filter_loc heap fun ~filter_loc {mem_pure} -> MemPure.range ~filter_loc mem_pure
let get_relation : t -> Relation.astate = fun m -> m.relation let get_relation : t -> Relation.astate = fun m -> m.relation
@ -882,30 +871,24 @@ module Mem = struct
fun f -> f_lift_default ~default:Bottom (fun m' -> NonBottom (f m')) fun f -> f_lift_default ~default:Bottom (fun m' -> NonBottom (f m'))
let find_stack : Loc.t -> t -> Val.t = let is_stack_loc : Loc.t -> t -> bool =
fun k -> f_lift_default ~default:Val.bot (MemReach.find_stack k) fun k -> f_lift_default ~default:false (MemReach.is_stack_loc k)
let find_stack_set : PowLoc.t -> t -> Val.t =
fun k -> f_lift_default ~default:Val.bot (MemReach.find_stack_set k)
let find_heap : Loc.t -> t -> Val.t =
fun k -> f_lift_default ~default:Val.bot (MemReach.find_heap k)
let find_heap_opt : Loc.t -> t -> Val.t option =
fun k -> f_lift_default ~default:None (MemReach.find_heap_opt k)
let find : Loc.t -> t -> Val.t = fun k -> f_lift_default ~default:Val.bot (MemReach.find k)
let find_heap_set : PowLoc.t -> t -> Val.t = let find_stack : Loc.t -> t -> Val.t =
fun k -> f_lift_default ~default:Val.bot (MemReach.find_heap_set k) fun k -> f_lift_default ~default:Val.bot (MemReach.find_stack k)
let find_set : PowLoc.t -> t -> Val.t = let find_set : PowLoc.t -> t -> Val.t =
fun k -> f_lift_default ~default:Val.bot (MemReach.find_set k) fun k -> f_lift_default ~default:Val.bot (MemReach.find_set k)
let find_opt : Loc.t -> t -> Val.t option =
fun k -> f_lift_default ~default:None (MemReach.find_opt k)
let find_alias : Ident.t -> t -> AliasTarget.t option = let find_alias : Ident.t -> t -> AliasTarget.t option =
fun k -> f_lift_default ~default:None (MemReach.find_alias k) fun k -> f_lift_default ~default:None (MemReach.find_alias k)
@ -934,6 +917,8 @@ module Mem = struct
fun formal loc e -> f_lift (MemReach.store_empty_alias formal loc e) fun formal loc e -> f_lift (MemReach.store_empty_alias formal loc e)
let add_stack_loc : Loc.t -> t -> t = fun k -> f_lift (MemReach.add_stack_loc k)
let add_stack : Loc.t -> Val.t -> t -> t = fun k v -> f_lift (MemReach.add_stack k v) let add_stack : Loc.t -> Val.t -> t -> t = fun k v -> f_lift (MemReach.add_stack k v)
let add_heap : Loc.t -> Val.t -> t -> t = fun k v -> f_lift (MemReach.add_heap k v) let add_heap : Loc.t -> Val.t -> t -> t = fun k v -> f_lift (MemReach.add_heap k v)
@ -947,13 +932,9 @@ module Mem = struct
fun id ~location -> f_lift (MemReach.add_unknown_from id ~callee_pname:None ~location) fun id ~location -> f_lift (MemReach.add_unknown_from id ~callee_pname:None ~location)
let strong_update_heap : PowLoc.t -> Val.t -> t -> t = let strong_update : PowLoc.t -> Val.t -> t -> t = fun p v -> f_lift (MemReach.strong_update p v)
fun p v -> f_lift (MemReach.strong_update_heap p v)
let weak_update_heap : PowLoc.t -> Val.t -> t -> t =
fun p v -> f_lift (MemReach.weak_update_heap p v)
let weak_update : PowLoc.t -> Val.t -> t -> t = fun p v -> f_lift (MemReach.weak_update p v)
let get_return : t -> Val.t = f_lift_default ~default:Val.bot MemReach.get_return let get_return : t -> Val.t = f_lift_default ~default:Val.bot MemReach.get_return

@ -83,7 +83,7 @@ let check_alloc_size size_exp {location} mem cond_set =
let set_uninitialized location (typ: Typ.t) ploc mem = let set_uninitialized location (typ: Typ.t) ploc mem =
match typ.desc with match typ.desc with
| Tint _ | Tfloat _ -> | Tint _ | Tfloat _ ->
Dom.Mem.weak_update_heap ploc Dom.Val.Itv.top mem Dom.Mem.weak_update ploc Dom.Val.Itv.top mem
| _ -> | _ ->
L.(debug BufferOverrun Verbose) L.(debug BufferOverrun Verbose)
"/!\\ Do not know how to uninitialize type %a at %a@\n" (Typ.pp Pp.text) typ Location.pp "/!\\ Do not know how to uninitialize type %a at %a@\n" (Typ.pp Pp.text) typ Location.pp
@ -336,7 +336,7 @@ module Collection = struct
let change_size_by ~size_f alist_id _ ~ret:_ mem = let change_size_by ~size_f alist_id _ ~ret:_ mem =
let alist_v = Dom.Mem.find_stack (Loc.of_id alist_id) mem in let alist_v = Dom.Mem.find (Loc.of_id alist_id) mem in
let locs = Dom.Val.get_pow_loc alist_v in let locs = Dom.Val.get_pow_loc alist_v in
Dom.Mem.transform_mem ~f:size_f locs mem Dom.Mem.transform_mem ~f:size_f locs mem

@ -140,9 +140,8 @@ let rec eval : Exp.t -> Mem.astate -> Val.t =
| Exp.Var id -> | Exp.Var id ->
Mem.find_stack (Var.of_id id |> Loc.of_var) mem Mem.find_stack (Var.of_id id |> Loc.of_var) mem
| Exp.Lvar pvar -> | Exp.Lvar pvar ->
let ploc = pvar |> Loc.of_pvar |> PowLoc.singleton in let ploc = Loc.of_pvar pvar in
let arr = Mem.find_stack_set ploc mem in if Mem.is_stack_loc ploc mem then Mem.find ploc mem else Val.of_loc ploc
ploc |> Val.of_pow_loc |> Val.join arr
| Exp.UnOp (uop, e, _) -> | Exp.UnOp (uop, e, _) ->
eval_unop uop e mem eval_unop uop e mem
| Exp.BinOp (bop, e1, e2) -> | Exp.BinOp (bop, e1, e2) ->
@ -249,7 +248,7 @@ let rec eval_arr : Exp.t -> Mem.astate -> Val.t =
| Exp.Var id -> ( | Exp.Var id -> (
match Mem.find_alias id mem with match Mem.find_alias id mem with
| Some (AliasTarget.Simple loc) -> | Some (AliasTarget.Simple loc) ->
Mem.find_heap loc mem Mem.find loc mem
| Some (AliasTarget.Empty _) | None -> | Some (AliasTarget.Empty _) | None ->
Val.bot ) Val.bot )
| Exp.Lvar pvar -> | Exp.Lvar pvar ->
@ -260,7 +259,7 @@ let rec eval_arr : Exp.t -> Mem.astate -> Val.t =
eval_arr e mem eval_arr e mem
| Exp.Lfield (e, fn, _) -> | Exp.Lfield (e, fn, _) ->
let locs = eval e mem |> Val.get_all_locs |> PowLoc.append_field ~fn in let locs = eval e mem |> Val.get_all_locs |> PowLoc.append_field ~fn in
Mem.find_heap_set locs mem Mem.find_set locs mem
| Exp.Lindex (e1, e2) -> | Exp.Lindex (e1, e2) ->
let arr = eval e1 mem in let arr = eval e1 mem in
let idx = eval e2 mem in let idx = eval e2 mem in
@ -290,11 +289,11 @@ module Prune = struct
| Exp.Var x -> ( | Exp.Var x -> (
match Mem.find_alias x mem with match Mem.find_alias x mem with
| Some (AliasTarget.Simple lv) -> | Some (AliasTarget.Simple lv) ->
let v = Mem.find_heap lv mem in let v = Mem.find lv mem in
let v' = Val.prune_ne_zero v in let v' = Val.prune_ne_zero v in
update_mem_in_prune lv v' astate update_mem_in_prune lv v' astate
| Some (AliasTarget.Empty lv) -> | Some (AliasTarget.Empty lv) ->
let v = Mem.find_heap lv mem in let v = Mem.find lv mem in
let v' = Val.prune_eq_zero v in let v' = Val.prune_eq_zero v in
update_mem_in_prune lv v' astate update_mem_in_prune lv v' astate
| None -> | None ->
@ -302,11 +301,11 @@ module Prune = struct
| Exp.UnOp (Unop.LNot, Exp.Var x, _) -> ( | Exp.UnOp (Unop.LNot, Exp.Var x, _) -> (
match Mem.find_alias x mem with match Mem.find_alias x mem with
| Some (AliasTarget.Simple lv) -> | Some (AliasTarget.Simple lv) ->
let v = Mem.find_heap lv mem in let v = Mem.find lv mem in
let v' = Val.prune_eq_zero v in let v' = Val.prune_eq_zero v in
update_mem_in_prune lv v' astate update_mem_in_prune lv v' astate
| Some (AliasTarget.Empty lv) -> | Some (AliasTarget.Empty lv) ->
let v = Mem.find_heap lv mem in let v = Mem.find lv mem in
let itv_v = Itv.prune_comp Binop.Ge (Val.get_itv v) Itv.one in let itv_v = Itv.prune_comp Binop.Ge (Val.get_itv v) Itv.one in
let v' = Val.modify_itv itv_v v in let v' = Val.modify_itv itv_v v in
update_mem_in_prune lv v' astate update_mem_in_prune lv v' astate
@ -325,7 +324,7 @@ module Prune = struct
| Exp.BinOp ((Binop.Ge as comp), Exp.Var x, e') -> ( | Exp.BinOp ((Binop.Ge as comp), Exp.Var x, e') -> (
match Mem.find_simple_alias x mem with match Mem.find_simple_alias x mem with
| Some lv -> | Some lv ->
let v = Mem.find_heap lv mem in let v = Mem.find lv mem in
let v' = Val.prune_comp comp v (eval e' mem) in let v' = Val.prune_comp comp v (eval e' mem) in
update_mem_in_prune lv v' astate update_mem_in_prune lv v' astate
| None -> | None ->
@ -333,7 +332,7 @@ module Prune = struct
| Exp.BinOp (Binop.Eq, Exp.Var x, e') -> ( | Exp.BinOp (Binop.Eq, Exp.Var x, e') -> (
match Mem.find_simple_alias x mem with match Mem.find_simple_alias x mem with
| Some lv -> | Some lv ->
let v = Mem.find_heap lv mem in let v = Mem.find lv mem in
let v' = Val.prune_eq v (eval e' mem) in let v' = Val.prune_eq v (eval e' mem) in
update_mem_in_prune lv v' astate update_mem_in_prune lv v' astate
| None -> | None ->
@ -341,7 +340,7 @@ module Prune = struct
| Exp.BinOp (Binop.Ne, Exp.Var x, e') -> ( | Exp.BinOp (Binop.Ne, Exp.Var x, e') -> (
match Mem.find_simple_alias x mem with match Mem.find_simple_alias x mem with
| Some lv -> | Some lv ->
let v = Mem.find_heap lv mem in let v = Mem.find lv mem in
let v' = Val.prune_ne v (eval e' mem) in let v' = Val.prune_ne v (eval e' mem) in
update_mem_in_prune lv v' astate update_mem_in_prune lv v' astate
| None -> | None ->
@ -437,11 +436,11 @@ let get_matching_pairs
let get_size_sym v = Val.get_size_sym v in let get_size_sym v = Val.get_size_sym v in
let get_field_name (fn, _, _) = fn in let get_field_name (fn, _, _) = fn in
let append_field v fn = PowLoc.append_field (Val.get_all_locs v) ~fn in let append_field v fn = PowLoc.append_field (Val.get_all_locs v) ~fn in
let deref_field v fn mem = Mem.find_heap_set (append_field v fn) mem in let deref_field v fn mem = Mem.find_set (append_field v fn) mem in
let deref_ptr v mem = let deref_ptr v mem =
let array_locs = Val.get_array_locs v in let array_locs = Val.get_array_locs v in
let locs = if PowLoc.is_empty array_locs then Val.get_pow_loc v else array_locs in let locs = if PowLoc.is_empty array_locs then Val.get_pow_loc v else array_locs in
Mem.find_heap_set locs mem Mem.find_set locs mem
in in
let ret_alias = ref None in let ret_alias = ref None in
let add_ret_alias v1 v2 = let add_ret_alias v1 v2 =
@ -563,7 +562,7 @@ let get_subst_map
* Relation.SubstMap.t = * Relation.SubstMap.t =
fun tenv callee_pdesc params caller_mem callee_symbol_table callee_exit_mem -> fun tenv callee_pdesc params caller_mem callee_symbol_table callee_exit_mem ->
let add_pair (formal, typ) (actual, actual_exp) (bound_l, ret_alias, rel_l) = let add_pair (formal, typ) (actual, actual_exp) (bound_l, ret_alias, rel_l) =
let callee_v = Mem.find_heap (Loc.of_pvar formal) callee_exit_mem in let callee_v = Mem.find (Loc.of_pvar formal) callee_exit_mem in
let new_bound_matching, ret_alias', new_rel_matching = let new_bound_matching, ret_alias', new_rel_matching =
get_matching_pairs tenv (Itv.SymbolPath.of_pvar formal) callee_v actual actual_exp typ get_matching_pairs tenv (Itv.SymbolPath.of_pvar formal) callee_v actual actual_exp typ
caller_mem callee_symbol_table callee_exit_mem caller_mem callee_symbol_table callee_exit_mem

@ -19,12 +19,12 @@ module TraceSet = Trace.Set
module Exec = struct module Exec = struct
let get_alist_size alist mem = let get_alist_size alist mem =
let size_powloc = Dom.Val.get_pow_loc alist in let size_powloc = Dom.Val.get_pow_loc alist in
Dom.Mem.find_heap_set size_powloc mem Dom.Mem.find_set size_powloc mem
let load_val id val_ mem = let load_val id val_ mem =
let locs = val_ |> Dom.Val.get_all_locs in let locs = val_ |> Dom.Val.get_all_locs in
let v = Dom.Mem.find_heap_set locs mem in let v = Dom.Mem.find_set locs mem in
let mem = Dom.Mem.add_stack (Loc.of_id id) v mem in let mem = Dom.Mem.add_stack (Loc.of_id id) v mem in
if PowLoc.is_singleton locs then Dom.Mem.load_simple_alias id (PowLoc.min_elt locs) mem if PowLoc.is_singleton locs then Dom.Mem.load_simple_alias id (PowLoc.min_elt locs) mem
else mem else mem
@ -155,7 +155,7 @@ module Exec = struct
let allocsite = Allocsite.make pname ~node_hash ~inst_num ~dimension in let allocsite = Allocsite.make pname ~node_hash ~inst_num ~dimension in
let offset, size = (Itv.zero, length) in let offset, size = (Itv.zero, length) in
let v = Dom.Val.of_array_alloc allocsite ~stride ~offset ~size in let v = Dom.Val.of_array_alloc allocsite ~stride ~offset ~size in
mem |> Dom.Mem.strong_update_heap field_loc v mem |> Dom.Mem.strong_update field_loc v
|> Dom.Mem.init_array_relation allocsite ~offset ~size ~size_exp_opt:None |> Dom.Mem.init_array_relation allocsite ~offset ~size ~size_exp_opt:None
| _ -> | _ ->
init_fields field_typ field_loc dimension ?dyn_length mem init_fields field_typ field_loc dimension ?dyn_length mem
@ -188,7 +188,7 @@ module Exec = struct
| Tarray {length= Some length} -> | Tarray {length= Some length} ->
let length = Itv.plus (Itv.of_int_lit length) dyn_length in let length = Itv.plus (Itv.of_int_lit length) dyn_length in
let v = Dom.Mem.find_set field_loc mem |> Dom.Val.set_array_size length in let v = Dom.Mem.find_set field_loc mem |> Dom.Val.set_array_size length in
Dom.Mem.strong_update_heap field_loc v mem Dom.Mem.strong_update field_loc v mem
| _ -> | _ ->
set_dyn_length tenv field_typ field_loc dyn_length mem ) set_dyn_length tenv field_typ field_loc dyn_length mem )
| _ -> | _ ->

@ -165,8 +165,7 @@ module BoundMap = struct
unreachable returning cost 0 \n" ; unreachable returning cost 0 \n" ;
BasicCost.zero BasicCost.zero
| NonBottom mem -> | NonBottom mem ->
BufferOverrunDomain.MemReach.heap_range ~filter_loc:(filter_loc control_vars) BufferOverrunDomain.MemReach.range ~filter_loc:(filter_loc control_vars) mem
mem
in in
L.(debug Analysis Medium) L.(debug Analysis Medium)
"@\n>>>Setting bound for node = %a to %a@\n\n" Node.pp_id node_id BasicCost.pp "@\n>>>Setting bound for node = %a to %a@\n\n" Node.pp_id node_id BasicCost.pp

Loading…
Cancel
Save