From 85c58cde12be60777172dd848009d793abc87d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr> Date: Thu, 17 Sep 2020 11:08:38 +0200 Subject: [PATCH] [Eva] In bases, locations, cvalue and lmap: adds function [replace_base]. --- src/kernel_services/abstract_interp/base.ml | 12 ++++++++++++ src/kernel_services/abstract_interp/base.mli | 6 ++++++ src/kernel_services/abstract_interp/lmap.ml | 8 ++++++++ src/kernel_services/abstract_interp/lmap_sig.mli | 2 ++ src/kernel_services/abstract_interp/locations.ml | 13 +++++++++++++ src/kernel_services/abstract_interp/locations.mli | 4 ++++ src/plugins/value_types/cvalue.ml | 4 ++++ src/plugins/value_types/cvalue.mli | 2 ++ 8 files changed, 51 insertions(+) diff --git a/src/kernel_services/abstract_interp/base.ml b/src/kernel_services/abstract_interp/base.ml index 0bfde596c3a..0c7e3ba7eec 100644 --- a/src/kernel_services/abstract_interp/base.ml +++ b/src/kernel_services/abstract_interp/base.ml @@ -452,6 +452,7 @@ module Base = struct let varname = Datatype.undefined end) let id = id + let pretty_debug = pretty end include Base @@ -549,6 +550,17 @@ let of_string_exp e = module SetLattice = Make_Hashconsed_Lattice_Set(Base)(Hptset) +module BMap = + Hptmap.Make (Base) (Base) (Hptmap.Comp_unused) + (struct let v = [ [] ] end) + (struct let l = [ Ast.self ] end) + +type substitution = base Hptmap.Shape(Base).t + +let substitution_from_list list = + let add map (key, elt) = BMap.add key elt map in + let bmap = List.fold_left add BMap.empty list in + BMap.shape bmap (* Local Variables: diff --git a/src/kernel_services/abstract_interp/base.mli b/src/kernel_services/abstract_interp/base.mli index 708c79c5579..ccebf749bbf 100644 --- a/src/kernel_services/abstract_interp/base.mli +++ b/src/kernel_services/abstract_interp/base.mli @@ -225,6 +225,12 @@ val register_memory_var : Cil_types.varinfo -> validity -> t They are created only to fill the contents of another variable. Their field [vsource] is set to false. *) +type substitution = base Hptmap.Shape(Base).t +(** Type used for the substitution between bases. *) + +val substitution_from_list: (base * base) list -> substitution +(** Creates a substitution from an association list. *) + (* Local Variables: compile-command: "make -C ../../.." diff --git a/src/kernel_services/abstract_interp/lmap.ml b/src/kernel_services/abstract_interp/lmap.ml index 46906585f76..b2223cda947 100644 --- a/src/kernel_services/abstract_interp/lmap.ml +++ b/src/kernel_services/abstract_interp/lmap.ml @@ -638,6 +638,14 @@ struct | Top -> Top | Map m -> Map (M.remove b m) + let replace_base shape = function + | Bottom -> Bottom + | Top -> Top + | Map map as t -> + let decide _key = Offsetmap.join in + let modified, map = M.replace_key ~decide shape map in + if modified then Map map else t + let is_reachable = function | Bottom -> false | Top | Map _ -> true diff --git a/src/kernel_services/abstract_interp/lmap_sig.mli b/src/kernel_services/abstract_interp/lmap_sig.mli index 9a7ac8d40b9..b9070fa559c 100644 --- a/src/kernel_services/abstract_interp/lmap_sig.mli +++ b/src/kernel_services/abstract_interp/lmap_sig.mli @@ -150,6 +150,8 @@ val filter_by_shape: 'a Hptmap.Shape(Base.Base).t -> t -> t (** Removes the base if it is present. Does nothing otherwise. *) val remove_base : Base.t -> t -> t +val replace_base: Base.substitution -> t -> t + (** {2 Iterators} *) diff --git a/src/kernel_services/abstract_interp/locations.ml b/src/kernel_services/abstract_interp/locations.ml index f5c126c7119..442b8d59bc6 100644 --- a/src/kernel_services/abstract_interp/locations.ml +++ b/src/kernel_services/abstract_interp/locations.ml @@ -358,6 +358,19 @@ module Location_Bytes = struct | Map _ -> false); true + let replace_base substitution v = + let substitute replace make acc = + let modified, set' = replace substitution acc in + modified, if modified then make set' else v + in + match v with + | Top (Base.SetLattice.Top, _) -> false, v + | Top (Base.SetLattice.Set set, origin) -> + substitute Base.Hptset.replace (inject_top_origin_internal origin) set + | Map map -> + let decide _key = Ival.join in + substitute (M.replace_key ~decide) (fun m -> Map m) map + let overlaps ~partial ~size mm1 mm2 = match mm1, mm2 with | Top _, _ | _, Top _ -> intersects mm1 mm2 diff --git a/src/kernel_services/abstract_interp/locations.mli b/src/kernel_services/abstract_interp/locations.mli index 760e1b93fa6..5157be7d4ed 100644 --- a/src/kernel_services/abstract_interp/locations.mli +++ b/src/kernel_services/abstract_interp/locations.mli @@ -78,6 +78,10 @@ module Location_Bytes : sig (** [add b i loc] binds [b] to [i] in [loc] when [i] is not {!Ival.bottom}, and returns {!bottom} otherwise. *) + val replace_base: Base.substitution -> t -> bool * t + (** [replace_base subst loc] changes the location [loc] by substituting the + pointed bases according to [subst]. *) + val diff : t -> t -> t (** Over-approximation of difference. [arg2] needs to be exact or an under_approximation. *) diff --git a/src/plugins/value_types/cvalue.ml b/src/plugins/value_types/cvalue.ml index a545314edfe..0fdd5f2fea5 100644 --- a/src/plugins/value_types/cvalue.ml +++ b/src/plugins/value_types/cvalue.ml @@ -909,6 +909,10 @@ module V_Or_Uninitialized = struct in removed, t' + let replace_base substitution t = + let modified, v = V.replace_base substitution (get_v t) in + modified, if modified then create (get_flags t) v else t + let reduce_by_initializedness pos v = if pos then meet v (C_init_esc V.top) diff --git a/src/plugins/value_types/cvalue.mli b/src/plugins/value_types/cvalue.mli index a5c93243c0b..717c387372f 100644 --- a/src/plugins/value_types/cvalue.mli +++ b/src/plugins/value_types/cvalue.mli @@ -226,6 +226,8 @@ module V_Or_Uninitialized : sig val unspecify_escaping_locals : exact:bool -> (V.M.key -> bool) -> t -> bool * t + val replace_base: Base.substitution -> t -> bool * t + val map: (V.t -> V.t) -> t -> t val map2: (V.t -> V.t -> V.t) -> t -> t -> t (** initialized/escaping information is the join of the information -- GitLab