From de4c7793187af93a2ce642bd9d4b027ed7053d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr> Date: Thu, 26 Mar 2020 11:03:27 +0100 Subject: [PATCH] [wp] implement OBJ validity access mode --- src/plugins/wp/Cvalues.ml | 5 ++ src/plugins/wp/Cvalues.mli | 1 + src/plugins/wp/LogicSemantics.ml | 6 +- src/plugins/wp/MemMemory.ml | 1 + src/plugins/wp/MemMemory.mli | 1 + src/plugins/wp/MemTyped.ml | 6 +- src/plugins/wp/MemVar.ml | 60 +++++++++++++------ src/plugins/wp/Sigs.ml | 1 + .../wp/share/why3/frama_c_wp/memory.mlw | 5 +- 9 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/plugins/wp/Cvalues.ml b/src/plugins/wp/Cvalues.ml index 5440affcb5d..10fa328fa1b 100644 --- a/src/plugins/wp/Cvalues.ml +++ b/src/plugins/wp/Cvalues.ml @@ -357,6 +357,11 @@ let plain lt e = type 'a printer = Format.formatter -> 'a -> unit +let pp_acs fmt = function + | RW -> Format.pp_print_string fmt "RW" + | RD -> Format.pp_print_string fmt "RD" + | OBJ -> Format.pp_print_string fmt "OBJ" + let pp_bound fmt = function None -> () | Some p -> F.pp_term fmt p let pp_value pp fmt = function diff --git a/src/plugins/wp/Cvalues.mli b/src/plugins/wp/Cvalues.mli index 1393505ab5a..f98a7923cb5 100644 --- a/src/plugins/wp/Cvalues.mli +++ b/src/plugins/wp/Cvalues.mli @@ -35,6 +35,7 @@ val equation : Sigs.equation -> pred type 'a printer = Format.formatter -> 'a -> unit +val pp_acs : acs printer val pp_bound : term option printer val pp_value : 'a printer -> 'a value printer val pp_logic : 'a printer -> 'a logic printer diff --git a/src/plugins/wp/LogicSemantics.ml b/src/plugins/wp/LogicSemantics.ml index 825ace458d1..2a90684fe56 100644 --- a/src/plugins/wp/LogicSemantics.ml +++ b/src/plugins/wp/LogicSemantics.ml @@ -871,11 +871,7 @@ struct | Pvalid(label,t) -> valid env RW label t | Pvalid_read(label,t) -> valid env RD label t - - | Pobject_pointer(_label,_t) -> - Warning.error - "\\object_pointer not yet implemented@\n\ - @[<hov 0>(%a)@]" Printer.pp_predicate p + | Pobject_pointer(label,t) -> valid env OBJ label t | Pvalid_function _t -> Warning.error diff --git a/src/plugins/wp/MemMemory.ml b/src/plugins/wp/MemMemory.ml index 4551f143c0d..8352296e1df 100644 --- a/src/plugins/wp/MemMemory.ml +++ b/src/plugins/wp/MemMemory.ml @@ -62,6 +62,7 @@ let l_havoc = Qed.Engine.{ let p_valid_rd = Lang.extern_fp ~library "valid_rd" let p_valid_rw = Lang.extern_fp ~library "valid_rw" +let p_valid_obj = Lang.extern_fp ~library "valid_obj" let p_invalid = Lang.extern_fp ~library "invalid" let p_separated = Lang.extern_fp ~library "separated" let p_included = Lang.extern_fp ~library "included" diff --git a/src/plugins/wp/MemMemory.mli b/src/plugins/wp/MemMemory.mli index 0a92156a9ed..ab60842d69a 100644 --- a/src/plugins/wp/MemMemory.mli +++ b/src/plugins/wp/MemMemory.mli @@ -62,6 +62,7 @@ val p_separated : lfun val p_included : lfun val p_valid_rd : lfun val p_valid_rw : lfun +val p_valid_obj : lfun val p_invalid : lfun val p_eqmem : lfun diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml index 9dce8f268df..e1317a92d94 100644 --- a/src/plugins/wp/MemTyped.ml +++ b/src/plugins/wp/MemTyped.ml @@ -954,7 +954,11 @@ let loc_diff obj p q = (* -------------------------------------------------------------------------- *) let s_valid sigma acs p n = - let p_valid = match acs with RW -> p_valid_rw | RD -> p_valid_rd in + let p_valid = match acs with + | RW -> p_valid_rw + | RD -> p_valid_rd + | OBJ -> p_valid_obj + in p_call p_valid [Sigma.value sigma T_alloc;p;n] let s_invalid sigma p n = diff --git a/src/plugins/wp/MemVar.ml b/src/plugins/wp/MemVar.ml index ca7a5873b1d..fd09f824c2c 100644 --- a/src/plugins/wp/MemVar.ml +++ b/src/plugins/wp/MemVar.ml @@ -739,6 +739,9 @@ struct let fits_inside cond a b n = p_leq e_zero a :: p_lt b (e_int n) :: cond + let fits_off_by_one cond a b n = + p_leq e_zero a :: p_leq b (e_int n) :: cond + let stay_outside cond a b n = p_lt b e_zero :: p_leq (e_int n) a :: cond @@ -754,6 +757,13 @@ struct | Some( _ , None ) -> unsized_array () | None -> raise ShiftMismatch + (* Append conditions for and array offset (te,k) to fits in obj *) + let array_check fitting cond te k obj = + match Ctypes.get_array obj with + | Some( e , Some n ) when Ctypes.equal e te -> fitting cond k k n + | Some( _ , None ) -> unsized_array () + | _ -> block_check fitting cond (obj,1) (te,k,k) + (* Append conditions for [offset] to fits [object], provided [a<=b]. *) let rec offset_fits cond obj offset = match offset with @@ -761,14 +771,8 @@ struct | Field fd :: ofs -> offset_fits cond (Ctypes.object_of fd.ftype) ofs | Shift(te,k) :: ofs -> - match Ctypes.get_array obj with - | Some( e , Some n ) when Ctypes.equal e te -> - let cond = p_leq e_zero k :: p_lt k (e_int n) :: cond in - offset_fits cond e ofs - | Some( _ , None ) -> unsized_array () - | _ -> - let cond = block_check fits_inside cond (obj,1) (te,k,k) in - offset_fits cond te ofs + let cond = array_check fits_inside cond te k obj in + offset_fits cond te ofs (* Append conditions to [cond] for [range=(elt,a,b)], starting at [offset], consisting of [a..b] elements with type [elt] to fits inside the block, @@ -796,19 +800,39 @@ struct (* --- Validity --- *) (* -------------------------------------------------------------------------- *) - let valid_offset obj ofs = - F.p_conj (offset_fits [] obj ofs) - - let valid_range obj ofs range = - F.p_conj (range_check fits_inside [] (obj,1) ofs range) + let rec last_field_shift acs obj ofs = + match acs , obj , ofs with + | OBJ , _ , [Shift(te,k)] -> Some(te,k,obj) + | OBJ , C_comp c , (Field fd :: ofs) -> + begin + match List.rev c.cfields with + | fd0::_ when Fieldinfo.equal fd fd0 -> + last_field_shift acs (Ctypes.object_of fd.ftype) ofs + | _ -> None + end + | _ -> None + + let valid_offset acs obj ofs = + match last_field_shift acs obj ofs with + | Some(te,k,obj) -> + F.p_conj (array_check fits_off_by_one [] te k obj) + | None -> + F.p_conj (offset_fits [] obj ofs) + + let valid_range acs obj ofs range = + match last_field_shift acs obj ofs with + | Some _ -> + F.p_conj (range_check fits_off_by_one [] (obj,1) ofs range) + | _ -> + F.p_conj (range_check fits_inside [] (obj,1) ofs range) (* varinfo *) let valid_base sigma acs mem x = if x.vglob then - if acs = RW && Cil.typeHasQualifier "const" x.vtype - then p_false - else p_true + match acs with + | RW -> if Cil.typeHasQualifier "const" x.vtype then p_false else p_true + | RD | OBJ -> p_true else match mem with | CVAL | HEAP -> p_bool (ALLOC.value sigma.alloc x) @@ -819,12 +843,12 @@ struct let valid_offset_path sigma acs mem x ofs = p_and (valid_base sigma acs mem x) - (valid_offset (vobject mem x) ofs) + (valid_offset acs (vobject mem x) ofs) let valid_range_path sigma acs mem x ofs rg = p_and (valid_base sigma acs mem x) - (valid_range (vobject mem x) ofs rg) + (valid_range acs (vobject mem x) ofs rg) (* in-model validation *) diff --git a/src/plugins/wp/Sigs.ml b/src/plugins/wp/Sigs.ml index c296519519c..72d1972ac59 100644 --- a/src/plugins/wp/Sigs.ml +++ b/src/plugins/wp/Sigs.ml @@ -46,6 +46,7 @@ type equation = type acs = | RW (** Read-Write Access *) | RD (** Read-Only Access *) + | OBJ (** Valid Object Pointer *) (** Abstract location or concrete value *) type 'a value = diff --git a/src/plugins/wp/share/why3/frama_c_wp/memory.mlw b/src/plugins/wp/share/why3/frama_c_wp/memory.mlw index 1dd6a2d7234..e91550d73ce 100644 --- a/src/plugins/wp/share/why3/frama_c_wp/memory.mlw +++ b/src/plugins/wp/share/why3/frama_c_wp/memory.mlw @@ -75,6 +75,9 @@ theory Memory predicate valid_rd (m : map int int) (p:addr) (n:int) = n > 0 -> ( 0 <> p.base /\ 0 <= p.offset /\ p.offset + n <= m[p.base] ) + predicate valid_obj (m : map int int) (p:addr) (n:int) = + n > 0 -> ( 0 <> p.base /\ 0 <= p.offset /\ p.offset + n <= 1 + m[p.base] ) + predicate invalid (m : map int int) (p:addr) (n:int) = n > 0 -> ( m[p.base] <= p.offset \/ p.offset + n <= 0 ) @@ -170,4 +173,4 @@ theory Memory axiom addr_of_null : int_of_addr null = 0 -end \ No newline at end of file +end -- GitLab