Skip to content
Snippets Groups Projects
Commit fc41ac53 authored by Valentin Perrelle's avatar Valentin Perrelle Committed by David Bühler
Browse files

[Eva] multidim: use better oracles whenever possible

parent 18cd9ce3
No related branches found
No related tags found
No related merge requests found
...@@ -379,9 +379,20 @@ struct ...@@ -379,9 +379,20 @@ struct
| Some s1, Some s2 -> Some (TrackedBases.union s1 s2) | Some s1, Some s2 -> Some (TrackedBases.union s1 s2)
(* Oracle conversion for Abstract_memory *)
let convert_oracle (oracle : Cil_types.exp -> value)
: Abstract_memory.oracle =
fun exp ->
try
Value.project_ival (oracle exp)
with Value.Not_based_on_null ->
Ival.top (* TODO: should it just not happen ? *)
(* Accesses *) (* Accesses *)
let rec read : let read :
type a . type a .
(memory -> offset -> a) -> (a -> a -> a) -> (memory -> offset -> a) -> (a -> a -> a) ->
state -> mdlocation -> a or_bottom = state -> mdlocation -> a or_bottom =
...@@ -392,17 +403,19 @@ struct ...@@ -392,17 +403,19 @@ struct
in in
Location.fold f loc `Bottom Location.fold f loc `Bottom
and get (state : state) (src : mdlocation) : value_or_uninitialized or_bottom = let get ~oracle
let oracle = mk_oracle state in (state : state) (src : mdlocation) : value_or_uninitialized or_bottom =
let oracle = convert_oracle oracle in
read (Memory.get ~oracle) Value_or_Uninitialized.join state src read (Memory.get ~oracle) Value_or_Uninitialized.join state src
and mk_oracle' (state : state) : Cil_types.exp -> value = let mk_oracle (state : state) : Cil_types.exp -> value =
(* Until Eva gives access to good oracles, we use this poor stupid oracle (* Until Eva gives access to good oracles, we use this poor stupid oracle
instead *) instead *)
let rec oracle exp = let rec oracle exp =
match exp.enode with match exp.enode with
| Lval lval -> | Lval lval ->
let value = get state (Location.of_lval oracle lval) in let loc = Location.of_lval oracle lval in
let value = get ~oracle state loc in
Value_or_Uninitialized.get_v (Bottom.non_bottom value) (* TODO: handle exception *) Value_or_Uninitialized.get_v (Bottom.non_bottom value) (* TODO: handle exception *)
| Const (CInt64 (i,_,_)) -> Value.inject_int i | Const (CInt64 (i,_,_)) -> Value.inject_int i
| Const (CReal (f,_,_)) -> Value.inject_float (Fval.singleton (Fval.F.of_float f)) | Const (CReal (f,_,_)) -> Value.inject_float (Fval.singleton (Fval.F.of_float f))
...@@ -423,23 +436,15 @@ struct ...@@ -423,23 +436,15 @@ struct
in in
fun exp -> oracle (Cil.constFold true exp) fun exp -> oracle (Cil.constFold true exp)
and convert_oracle (oracle : Cil_types.exp -> value) let mk_bioracle s1 s2 =
: Abstract_memory.oracle = let oracle_left = mk_oracle s1
fun exp -> and oracle_right = mk_oracle s2 in
try function
Value.project_ival (oracle exp) | Abstract_memory.Left -> convert_oracle oracle_left
with Value.Not_based_on_null -> | Right -> convert_oracle oracle_right
Ival.top (* TODO: should it just not happen ? *)
and convert_oracle_or_default state = function (* TODO: use everywhere *)
| Some oracle -> convert_oracle oracle
| None -> mk_oracle state
and mk_oracle (state : state) : Abstract_memory.oracle =
convert_oracle (mk_oracle' state)
let extract (state : state) (src : mdlocation) : Memory.t or_bottom = let extract ~oracle (state : state) (src : mdlocation) : Memory.t or_bottom =
let oracle = mk_oracle state in let oracle = convert_oracle oracle in
read (Memory.extract ~oracle) (Memory.smash ~oracle) state src read (Memory.extract ~oracle) (Memory.smash ~oracle) state src
let add_references (base_map,tracked) vi refs' = let add_references (base_map,tracked) vi refs' =
...@@ -469,29 +474,32 @@ struct ...@@ -469,29 +474,32 @@ struct
(* Result can never be bottom if update never returns bottom *) (* Result can never be bottom if update never returns bottom *)
Bottom.non_bottom (write' (fun m o -> `Value (update m o)) state loc) Bottom.non_bottom (write' (fun m o -> `Value (update m o)) state loc)
let set (state : state) (dst : mdlocation) (v : value_or_uninitialized) : state = let set ~oracle
(state : state) (dst : mdlocation) (v : value_or_uninitialized) : state =
let weak = not (Location.is_singleton dst) let weak = not (Location.is_singleton dst)
and oracle = mk_oracle state in and oracle = convert_oracle oracle in
write (Memory.set ~oracle ~weak v) state dst write (Memory.set ~oracle ~weak v) state dst
let overwrite (state : state) (dst : mdlocation) (src : mdlocation) : state = let overwrite ~oracle
let weak = not (Location.is_singleton dst) (state : state) (dst : mdlocation) (src : mdlocation) : state =
and oracle = mk_oracle state in let weak = not (Location.is_singleton dst) in
match extract state src with match extract ~oracle state src with
| `Bottom -> state (* no source *) | `Bottom -> state (* no source *)
| `Value value -> | `Value value ->
let oracle = convert_oracle oracle in
write (fun m off -> Memory.overwrite ~oracle ~weak m off value) state dst write (fun m off -> Memory.overwrite ~oracle ~weak m off value) state dst
let erase (state : state) (dst : mdlocation) (b : Abstract_memory.bit): state = let erase ~oracle
(state : state) (dst : mdlocation) (b : Abstract_memory.bit): state =
let weak = not (Location.is_singleton dst) let weak = not (Location.is_singleton dst)
and oracle = mk_oracle state in and oracle = convert_oracle oracle in
write (fun m off -> Memory.erase ~oracle ~weak m off b) state dst write (fun m off -> Memory.erase ~oracle ~weak m off b) state dst
let reinforce let reinforce
?oracle ~oracle
(f : value_or_uninitialized -> value_or_uninitialized or_bottom) (f : value_or_uninitialized -> value_or_uninitialized or_bottom)
(state : state) (dst : mdlocation) : state or_bottom = (state : state) (dst : mdlocation) : state or_bottom =
let oracle = convert_oracle_or_default state oracle in let oracle = convert_oracle oracle in
write' (fun m off -> Memory.reinforce ~oracle f m off) state dst write' (fun m off -> Memory.reinforce ~oracle f m off) state dst
(* Lattice *) (* Lattice *)
...@@ -517,12 +525,8 @@ struct ...@@ -517,12 +525,8 @@ struct
let narrow = join ~cache ~symmetric:false ~idempotent:true ~decide in let narrow = join ~cache ~symmetric:false ~idempotent:true ~decide in
fun (m1,t1) (m2,t2) -> `Value (narrow m1 m2, join_tracked t1 t2) fun (m1,t1) (m2,t2) -> `Value (narrow m1 m2, join_tracked t1 t2)
let join (m1,t1 as s1) (m2,t2 as s2) = let join' ~oracle (m1,t1) (m2,t2) =
let open BaseMap in let open BaseMap in
let oracle = function
| Abstract_memory.Left -> mk_oracle s1
| Right -> mk_oracle s2
in
let cache = Hptmap_sig.NoCache let cache = Hptmap_sig.NoCache
and decide _ (m1,r1) (m2,r2) = and decide _ (m1,r1) (m2,r2) =
let m = Memory.join ~oracle m1 m2 let m = Memory.join ~oracle m1 m2
...@@ -532,12 +536,13 @@ struct ...@@ -532,12 +536,13 @@ struct
inter ~cache ~symmetric:false ~idempotent:true ~decide m1 m2, inter ~cache ~symmetric:false ~idempotent:true ~decide m1 m2,
join_tracked t1 t2 join_tracked t1 t2
let join s1 s2 =
let oracle = mk_bioracle s1 s2 in
join' ~oracle s1 s2
let widen kf stmt (m1,t1 as s1) (m2,t2 as s2) = let widen kf stmt (m1,t1 as s1) (m2,t2 as s2) =
let open BaseMap in let open BaseMap in
let oracle = function let oracle = mk_bioracle s1 s2
| Abstract_memory.Left -> mk_oracle s1
| Right -> mk_oracle s2
and _,get_hints = Widen.getWidenHints kf stmt in and _,get_hints = Widen.getWidenHints kf stmt in
let cache = Hptmap_sig.NoCache let cache = Hptmap_sig.NoCache
and decide base (m1,r1) (m2,r2) = and decide base (m1,r1) (m2,r2) =
...@@ -568,7 +573,7 @@ struct ...@@ -568,7 +573,7 @@ struct
in in
try try
let loc = Location.of_lval oracle lv in let loc = Location.of_lval oracle lv in
let v = get state loc in let v = get ~oracle state loc in
(v >>-: fun v -> (Value_or_Uninitialized.get_v v, None)), (v >>-: fun v -> (Value_or_Uninitialized.get_v v, None)),
match v with match v with
| `Bottom -> Alarmset.all | `Bottom -> Alarmset.all
...@@ -639,6 +644,7 @@ struct ...@@ -639,6 +644,7 @@ struct
let references = snd (BaseMap.find_or_top base_map (Base.of_varinfo vi)) in let references = snd (BaseMap.find_or_top base_map (Base.of_varinfo vi)) in
let update_ref base base_map = let update_ref base base_map =
let update (memory, refs) = let update (memory, refs) =
let oracle = convert_oracle oracle in
Memory.incr_bound ~oracle vi incr memory, refs Memory.incr_bound ~oracle vi incr memory, refs
in in
BaseMap.replace (Option.map update) base base_map BaseMap.replace (Option.map update) base base_map
...@@ -672,13 +678,13 @@ struct ...@@ -672,13 +678,13 @@ struct
let dst = Location.of_lval oracle lval in let dst = Location.of_lval oracle lval in
match assigned_value with match assigned_value with
| Assign value -> | Assign value ->
set state dst (Value_or_Uninitialized.of_value value) set ~oracle state dst (Value_or_Uninitialized.of_value value)
| Copy (right, _value) -> | Copy (right, _value) ->
try try
let src = Location.of_lval oracle right.lval in let src = Location.of_lval oracle right.lval in
overwrite state dst src overwrite ~oracle state dst src
with Abstract_interp.Error_Top | Abstract_interp.Error_Bottom -> with Abstract_interp.Error_Top | Abstract_interp.Error_Bottom ->
erase state dst Abstract_memory.Bit.top erase ~oracle state dst Abstract_memory.Bit.top
with Abstract_interp.Error_Top | Abstract_interp.Error_Bottom -> with Abstract_interp.Error_Top | Abstract_interp.Error_Bottom ->
(* Failed to evaluate the left location *) (* Failed to evaluate the left location *)
top top
...@@ -717,7 +723,7 @@ struct ...@@ -717,7 +723,7 @@ struct
begin try begin try
let oracle = make_oracle valuation in let oracle = make_oracle valuation in
let loc = Location.of_lval oracle lval in let loc = Location.of_lval oracle lval in
match extract state loc with match extract ~oracle state loc with
| `Bottom -> Format.fprintf fmt "⊥" | `Bottom -> Format.fprintf fmt "⊥"
| `Value value -> Memory.pretty fmt value | `Value value -> Memory.pretty fmt value
with Abstract_interp.Error_Top | Abstract_interp.Error_Bottom -> with Abstract_interp.Error_Top | Abstract_interp.Error_Bottom ->
...@@ -727,9 +733,10 @@ struct ...@@ -727,9 +733,10 @@ struct
| _ -> () | _ -> ()
let enter_scope _kind vars state = let enter_scope _kind vars state =
let oracle = mk_oracle state in
let enter_one state v = let enter_one state v =
let dst = Location.of_var v in let dst = Location.of_var v in
erase state dst Abstract_memory.Bit.uninitialized erase ~oracle state dst Abstract_memory.Bit.uninitialized
in in
List.fold_left enter_one state vars List.fold_left enter_one state vars
...@@ -750,7 +757,8 @@ struct ...@@ -750,7 +757,8 @@ struct
match sources with match sources with
| [] -> | [] ->
let dst = Location.of_precise_loc location in let dst = Location.of_precise_loc location in
erase state dst Abstract_memory.Bit.numerical let oracle = mk_oracle state in
erase ~oracle state dst Abstract_memory.Bit.numerical
| _ -> | _ ->
BaseMap.remove_loc base_map location, tracked BaseMap.remove_loc base_map location, tracked
...@@ -761,8 +769,9 @@ struct ...@@ -761,8 +769,9 @@ struct
let loc,typ = Location.of_term env arg in let loc,typ = Location.of_term env arg in
begin match Cil.unrollType (Logic_utils.logicCType typ) with begin match Cil.unrollType (Logic_utils.logicCType typ) with
| TFloat (fkind,_) -> | TFloat (fkind,_) ->
let update = Value.backward_is_finite positive fkind in let update = Value.backward_is_finite positive fkind
reinforce (Value_or_Uninitialized.map' update) state loc and oracle = mk_oracle state in
reinforce ~oracle (Value_or_Uninitialized.map' update) state loc
| _ | exception (Failure _) -> `Value state | _ | exception (Failure _) -> `Value state
end end
| _ -> `Value state | _ -> `Value state
...@@ -788,9 +797,10 @@ struct ...@@ -788,9 +797,10 @@ struct
let vi,offset,bounds = annotation in let vi,offset,bounds = annotation in
(* Update the segmentation *) (* Update the segmentation *)
let lval = Cil_types.Var vi, offset in let lval = Cil_types.Var vi, offset in
let loc = Location.of_lval (mk_oracle' state) lval in
let oracle = mk_oracle state in let oracle = mk_oracle state in
let loc = Location.of_lval oracle lval in
let update m offset = let update m offset =
let oracle = convert_oracle oracle in
Memory.segmentation_hint ~oracle m offset bounds Memory.segmentation_hint ~oracle m offset bounds
in in
let state = write update state loc in let state = write update state loc in
...@@ -821,12 +831,14 @@ struct ...@@ -821,12 +831,14 @@ struct
| Abstract_domain.Top -> Abstract_memory.Bit.numerical | Abstract_domain.Top -> Abstract_memory.Bit.numerical
| Abstract_domain.Zero -> Abstract_memory.Bit.zero | Abstract_domain.Zero -> Abstract_memory.Bit.zero
in in
erase state dst d let oracle = mk_oracle state in (* Since dst has no offset, oracle is actyally useless *)
erase ~oracle state dst d
let initialize_variable_using_type _kind vi state = let initialize_variable_using_type _kind vi state =
let lval = Cil.var vi in let lval = Cil.var vi in
let dst = Location.of_lval no_oracle lval in let dst = Location.of_lval no_oracle lval in
erase state dst Abstract_memory.Bit.top let oracle = mk_oracle state in (* Since dst has no offset, oracle is actyally useless *)
erase ~oracle state dst Abstract_memory.Bit.top
let relate _kf _bases _state = Base.SetLattice.empty let relate _kf _bases _state = Base.SetLattice.empty
...@@ -850,13 +862,11 @@ end ...@@ -850,13 +862,11 @@ end
include Domain include Domain
let multidim_top = top
let better_join _oracle_left _oracle_right a b = join a b
let multidim_hook (module Abstract: Abstractions.S) : (module Abstractions.S) = let multidim_hook (module Abstract: Abstractions.S) : (module Abstractions.S) =
match Abstract.Dom.get key with match Abstract.Val.get Main_values.CVal.key, Abstract.Dom.get key with
| None -> (module Abstract) | None, _
| Some get_multidim -> | _, None -> (module Abstract)
| Some get_cval, Some get_multidim ->
let module Eval = let module Eval =
Evaluation.Make (Abstract.Val) (Abstract.Loc) (Abstract.Dom) Evaluation.Make (Abstract.Val) (Abstract.Loc) (Abstract.Dom)
in in
...@@ -864,13 +874,19 @@ let multidim_hook (module Abstract: Abstractions.S) : (module Abstractions.S) = ...@@ -864,13 +874,19 @@ let multidim_hook (module Abstract: Abstractions.S) : (module Abstractions.S) =
include Abstract.Dom include Abstract.Dom
let join a b = let join a b =
let r = join (set key multidim_top a) (set key multidim_top b) in let r = join (set key Domain.top a) (set key Domain.top b) in
let left_oracle = Eval.evaluate a in let oracle state exp = (* TODO: cache results *)
let right_oracle = Eval.evaluate b in let v, _alarms = Eval.evaluate state exp in
let taint = match v with
better_join left_oracle right_oracle (get_multidim a) (get_multidim b) | `Bottom -> Cvalue.V.top
| `Value (_valuation,v) -> get_cval v
in
let oracle = function
| Abstract_memory.Left -> Domain.convert_oracle (oracle a)
| Abstract_memory.Right -> Domain.convert_oracle (oracle b)
in in
set key taint r let multidim = Domain.join' ~oracle (get_multidim a) (get_multidim b) in
set key multidim r
end end
in in
(module struct (module struct
......
...@@ -174,7 +174,7 @@ void main9(void) { ...@@ -174,7 +174,7 @@ void main9(void) {
//@ eva_domain_scope multidim,t1; //@ eva_domain_scope multidim,t1;
for (int i = 0 ; i < 10 ; i++) { for (int i = 0 ; i < 10 ; i++) {
//@ eva_domain_scope multidim,i;
t1[i] = 0; t1[i] = 0;
t2[i] = 0; t2[i] = 0;
} }
......
...@@ -220,7 +220,7 @@ ...@@ -220,7 +220,7 @@
[eva] multidim.c:182: [eva] multidim.c:182:
Frama_C_domain_show_each: Frama_C_domain_show_each:
t1 : # cvalue: {0} or UNINITIALIZED t1 : # cvalue: {0} or UNINITIALIZED
# multidim: [0 .. 9] = {0} or UNINITIALIZED # multidim: { [0 .. i - 1] = {0}, [i .. 9] = UNINITIALIZED }
t2 : # cvalue: {0} or UNINITIALIZED t2 : # cvalue: {0} or UNINITIALIZED
# multidim: UNINITIALIZED # multidim: UNINITIALIZED
[eva] Recording results for main9 [eva] Recording results for main9
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment