diff --git a/ALL_VERSIONS b/ALL_VERSIONS index 64a0142c4f5a63aa2842858db8ec8c9b12698818..731e28b1da14b733e369c8601618ff5fd2196e87 100644 --- a/ALL_VERSIONS +++ b/ALL_VERSIONS @@ -1,6 +1,7 @@ Version number Date of release Notes ============== =============== ===== -23.0 (Vanadium) 2021, June 28 +23.1 (Vanadium) 2021, July 20 +23.0 (Vanadium) 2021, July 7 22.0 (Titanium) 2020, November 17 21.1 (Scandium) 2020, June 25 Bugs fixed 21.0 (Scandium) 2020, June 11 diff --git a/Changelog b/Changelog index 4f057090fcd8e5dc3e7e5d0ded399971050cc307..e797181966e498d749f96bc11d03023010523273 100644 --- a/Changelog +++ b/Changelog @@ -25,6 +25,10 @@ o Kernel [2021-06-10] New module Cil_builder, simplifies C and ACSL code o Ptests [2021-06-03] Add new PLUGIN directive and new predefined macros. - Eva [2021-05-11] Support for ACSL predicate \is_infinite. +################################### +Open Source Release 23.1 (Vanadium) +################################### + ################################### Open Source Release 23.0 (Vanadium) ################################### diff --git a/VERSION b/VERSION index 1d37314c457169b4e9ce45deac798ae467fbc459..930e9e656373bd9c3a4939e14ebdad9bf7daaca9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -23.0+dev +23.1+dev diff --git a/opam/opam b/opam/opam index bba7a550a8ca6624b6abcd1696a328c1bfa954e8..4ca43003a0b54d07e8ae15487b96b8e804b582aa 100644 --- a/opam/opam +++ b/opam/opam @@ -1,7 +1,7 @@ opam-version: "2.0" name: "frama-c" synopsis: "Platform dedicated to the analysis of source code written in C" -version: "23.0" +version: "23.1" description:""" Frama-C gathers several analysis techniques in a single collaborative framework, based on analyzers (called "plug-ins") that can build upon the @@ -99,7 +99,7 @@ install: [ ] run-test: [ - [make "-j%{jobs}%" "PTESTS_OPTS=-error-code" "tests"] { arch != "ppc64" } + [make "-j%{jobs}%" "PTESTS_OPTS=-error-code" "tests"] { arch != "ppc64" & arch != "x86_32" & arch != "arm32" } # tests are disabled on PPC64 due to floating-point oracle differences # (some ULPs in libc trigonometric functions) and due to the lack of # available hardware to test them locally @@ -115,12 +115,12 @@ depends: [ ( "alt-ergo-free" | "alt-ergo" ) "conf-graphviz" { post } "conf-time" { with-test } - "ocaml" { >= "4.08.1" } + "ocaml" { >= "4.08.1" & < "4.13.0" } "ocamlfind" # needed beyond build stage, used by -load-module "ocamlgraph" { >= "1.8.8" } "why3" { >= "1.4.0" & < "1.5~" } - "yojson" - "zarith" + "yojson" {>= "1.6.0"} + "zarith" {>= "1.5"} ] depopts: [ diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog index c05704c94c67baf0658a7209701a7be811bfffd2..6b448f789441d6b8d95e5a5a1acd19e4d2ded92c 100644 --- a/src/plugins/e-acsl/doc/Changelog +++ b/src/plugins/e-acsl/doc/Changelog @@ -25,12 +25,6 @@ Plugin E-ACSL <next-release> ############################ --* E-ACSL [2021-07-19] Fix crash occurring when two or more successive - logic coercions were done in a term (frama-c/e-acsl#172). --* E-ACSL [2021-07-19] Fix crash when raising some user errors - (frama-c/e-acsl#170). --* E-ACSL [2021-07-16] Fix crash when using some built-in labels - (frama-c/e-acsl#173). - E-ACSL [2021-07-06] Add support for the extended quantifier \sum. -* E-ACSL [2021-06-22] Fix a crash that occured when using certain combinations of nested blocks and annotations. @@ -40,6 +34,19 @@ Plugin E-ACSL <next-release> range indices (frama-c/e-acsl#148). -* E-ACSL [2021-06-04] Do not translate contracts of E-ACSL built-ins. +############################# +Plugin E-ACSL 23.1 (Vanadium) +############################# + +-* E-ACSL [2021-07-19] Fix crash occurring when two or more successive + logic coercions were done in a term (frama-c/e-acsl#172). +-* E-ACSL [2021-07-19] Fix crash when raising some user errors + (frama-c/e-acsl#170). +-* E-ACSL [2021-07-16] Fix crash when using some built-in labels + (frama-c/e-acsl#173). +-* E-ACSL [2021-07-13] Fix crash when encountering a GMP value in a loop + variant (frama-c/e-acsl#169). + ############################# Plugin E-ACSL 23.0 (Vanadium) ############################# diff --git a/src/plugins/e-acsl/src/code_generator/loops.ml b/src/plugins/e-acsl/src/code_generator/loops.ml index 656f790c6b03964797ddc44cf27dd361cb7cb684..c6d6e726ba7e5f183f42551b3bba4e57472811ad 100644 --- a/src/plugins/e-acsl/src/code_generator/loops.ml +++ b/src/plugins/e-acsl/src/code_generator/loops.ml @@ -48,32 +48,37 @@ let handle_annotations env kf stmt = | Loop(_, ({ bstmts = stmts } as blk), loc, cont, break) -> (* Loop variant, save the current value of the variant *) let stmts, env, variant = - match Env.top_loop_variant env with - | Some (t, measure_opt) -> - let env = Env.set_annotation_kind env Smart_stmt.Variant in - let env = Env.push env in - Typing.type_term ~use_gmp_opt:true t; - let ty = Typing.get_typ t in - let e, env = !term_to_exp_ref kf env t in - let vi_old, e_old, env = - Env.new_var - ~loc - ~scope:Varname.Function - ~name:"old_variant" - env - kf - (Some t) - ty - (fun _ _ -> []) - in - let stmt = - Smart_stmt.assigns ~loc ~result:(Cil.var vi_old) e - in - let blk, env = - Env.pop_and_get env stmt ~global_clear:false Env.Middle - in - Smart_stmt.block_stmt blk :: stmts, env, Some (t, e_old, measure_opt) - | None -> stmts, env, None + Error.handle + (fun (stmts, env, _) -> + match Env.top_loop_variant env with + | Some (t, measure_opt) -> + let env = Env.set_annotation_kind env Smart_stmt.Variant in + let env = Env.push env in + Typing.type_term ~use_gmp_opt:true t; + let ty = Typing.get_typ t in + if Gmp_types.is_t ty then Error.not_yet "loop variant using GMP"; + let e, env = !term_to_exp_ref kf env t in + let vi_old, e_old, env = + Env.new_var + ~loc + ~scope:Varname.Function + ~name:"old_variant" + env + kf + (Some t) + ty + (fun _ _ -> []) + in + let stmt = + Smart_stmt.assigns ~loc ~result:(Cil.var vi_old) e + in + let blk, env = + Env.pop_and_get env stmt ~global_clear:false Env.Middle + in + let stmts = Smart_stmt.block_stmt blk :: stmts in + stmts, env, Some (t, e_old, measure_opt) + | None -> stmts, env, None) + (stmts, env, None) in (* Auxiliary function to generate variant and invariant checks *) let rec aux (stmts, env) = function @@ -118,14 +123,23 @@ let handle_annotations env kf stmt = stmts, env | Some (t, e_old, None) -> let env = Env.push env in - Typing.type_term ~use_gmp_opt:true t; - let e, env = !term_to_exp_ref kf env t in + let t_old = Logic_utils.expr_to_term e_old in + let variant_pos = + Logic_const.prel ~loc (Rge, t_old, Logic_const.tinteger ~loc 0) + in + Typing.type_named_predicate ~must_clear:true variant_pos; + let variant_pos_e, env = !predicate_to_exp_ref kf env variant_pos in let msg1 = Format.asprintf "(old %a) %a 0" Printer.pp_term t Printer.pp_relation Rge in + let variant_dec = + Logic_const.prel ~loc (Rgt, t_old, t) + in + Typing.type_named_predicate ~must_clear:true variant_dec; + let variant_dec_e, env = !predicate_to_exp_ref kf env variant_dec in let msg2 = Format.asprintf "(old %a) > %a" @@ -140,14 +154,14 @@ let handle_annotations env kf stmt = ~pred_kind:Assert Smart_stmt.Variant kf - (Cil.mkBinOp ~loc Ge e_old (Cil.zero ~loc)); + variant_pos_e; Smart_stmt.runtime_check_with_msg ~loc msg2 ~pred_kind:Assert Smart_stmt.Variant kf - (Cil.mkBinOp ~loc Gt e_old e) + variant_dec_e ] in let blk, env = diff --git a/src/plugins/e-acsl/tests/constructs/decrease.i b/src/plugins/e-acsl/tests/constructs/decrease.c similarity index 82% rename from src/plugins/e-acsl/tests/constructs/decrease.i rename to src/plugins/e-acsl/tests/constructs/decrease.c index 4bb96675366a34026d543101466313a8add9cb9e..4e32701dbebbabe29db2ce924d45c7f7df62d1e4 100644 --- a/src/plugins/e-acsl/tests/constructs/decrease.i +++ b/src/plugins/e-acsl/tests/constructs/decrease.c @@ -2,6 +2,8 @@ STDOPT: +"-eva-unroll-recursive-calls 10 -eva-slevel 7" */ +#include <stddef.h> + // Test that the last iteration of the variant can be negative int f(int x) { /*@ loop variant x; */ @@ -35,6 +37,18 @@ int fact(int n) { return result; } +// Test GMP variant +/*@ requires n <= 20; */ +size_t fact2(size_t n) { + size_t result = n; + /*@ loop invariant 1 <= i < n; + loop variant n - i; */ + for (size_t i = 1UL ; i < (n - 1UL) ; i++) { + result *= (n - i); + } + return result; +} + // Test decreases on recursive function /*@ decreases n; */ int fib(int n) { @@ -71,6 +85,9 @@ int main() { int fact7 = fact(7); //@ assert fact7 == 5040; + size_t fact18 = fact2(18); + //@ assert fact18 == 6402373705728000UL; + int fib7 = fib(7); //@ assert fib7 == 13; diff --git a/src/plugins/e-acsl/tests/constructs/oracle/decrease.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle/decrease.res.oracle index 2a909408ab28551a31c8128f578c384ab0e246df..677ba8aacfddbb93a3fc0644b971456fc44ec92f 100644 --- a/src/plugins/e-acsl/tests/constructs/oracle/decrease.res.oracle +++ b/src/plugins/e-acsl/tests/constructs/oracle/decrease.res.oracle @@ -1,11 +1,16 @@ [e-acsl] beginning translation. -[e-acsl] tests/constructs/decrease.i:50: Warning: +[e-acsl] tests/constructs/decrease.c:45: Warning: + E-ACSL construct `loop variant using GMP' is not yet supported. + Ignoring annotation. +[e-acsl] tests/constructs/decrease.c:64: Warning: E-ACSL construct `decreases clause' is not yet supported. Ignoring annotation. -[e-acsl] tests/constructs/decrease.i:47: Warning: +[e-acsl] tests/constructs/decrease.c:61: Warning: E-ACSL construct `decreases clause' is not yet supported. Ignoring annotation. -[e-acsl] tests/constructs/decrease.i:40: Warning: +[e-acsl] tests/constructs/decrease.c:54: Warning: E-ACSL construct `decreases clause' is not yet supported. Ignoring annotation. [e-acsl] translation done in project "e-acsl". +[eva:alarm] tests/constructs/decrease.c:89: Warning: + function __e_acsl_assert, behavior blocking: precondition got status unknown. diff --git a/src/plugins/e-acsl/tests/constructs/oracle/gen_decrease.c b/src/plugins/e-acsl/tests/constructs/oracle/gen_decrease.c index 116816df289b37cce0dcf9fe63c4b5fe6b748abf..f7b974205400d3cc2e7b01e80412975f1a7a9a96 100644 --- a/src/plugins/e-acsl/tests/constructs/oracle/gen_decrease.c +++ b/src/plugins/e-acsl/tests/constructs/oracle/gen_decrease.c @@ -12,9 +12,10 @@ int f(int x) if (! (x >= 0)) break; x -= 2; __e_acsl_assert(__gen_e_acsl_old_variant >= 0,1,"Variant","f", - "(old x) \342\211\245 0","tests/constructs/decrease.i",8); + "(old x) \342\211\245 0","tests/constructs/decrease.c", + 10); __e_acsl_assert(__gen_e_acsl_old_variant > x,1,"Variant","f", - "(old x) > x","tests/constructs/decrease.i",8); + "(old x) > x","tests/constructs/decrease.c",10); } return x; } @@ -36,7 +37,7 @@ int g(int x) int __gen_e_acsl_lexico_2; __gen_e_acsl_lexico_2 = __gen_e_acsl_lexico(__gen_e_acsl_old_variant,x); __e_acsl_assert(__gen_e_acsl_lexico_2,1,"Variant","g", - "lexico(old x, x)","tests/constructs/decrease.i",19); + "lexico(old x, x)","tests/constructs/decrease.c",21); } } return x; @@ -50,7 +51,7 @@ int fact(int n) int __gen_e_acsl_old_variant; int result = n; __e_acsl_assert(n >= 1,1,"Invariant","fact","n >= 1", - "tests/constructs/decrease.i",29); + "tests/constructs/decrease.c",31); /*@ loop invariant n ≥ 1; loop variant n; */ while (1) { @@ -59,12 +60,43 @@ int fact(int n) result *= n - 1; n --; __e_acsl_assert(n >= 1,1,"Invariant","fact","n >= 1", - "tests/constructs/decrease.i",29); + "tests/constructs/decrease.c",31); __e_acsl_assert(__gen_e_acsl_old_variant >= 0,1,"Variant","fact", - "(old n) \342\211\245 0","tests/constructs/decrease.i", - 31); + "(old n) \342\211\245 0","tests/constructs/decrease.c", + 33); __e_acsl_assert(__gen_e_acsl_old_variant > n,1,"Variant","fact", - "(old n) > n","tests/constructs/decrease.i",31); + "(old n) > n","tests/constructs/decrease.c",33); + } + return result; +} + +/*@ requires n ≤ 20; */ +size_t __gen_e_acsl_fact2(size_t n); + +size_t fact2(size_t n) +{ + size_t result = n; + { + size_t i = 1UL; + { + int __gen_e_acsl_and; + if (1UL <= i) __gen_e_acsl_and = i < n; else __gen_e_acsl_and = 0; + __e_acsl_assert(__gen_e_acsl_and,1,"Invariant","fact2","1 <= i < n", + "tests/constructs/decrease.c",44); + } + /*@ loop invariant 1 ≤ i < n; + loop variant n - i; */ + while (i < n - 1UL) { + result *= n - i; + { + int __gen_e_acsl_and_2; + i += (size_t)1; + if (1UL <= i) __gen_e_acsl_and_2 = i < n; + else __gen_e_acsl_and_2 = 0; + __e_acsl_assert(__gen_e_acsl_and_2,1,"Invariant","fact2", + "1 <= i < n","tests/constructs/decrease.c",44); + } + } } return result; } @@ -132,43 +164,48 @@ int main(void) int __retres; int f10 = f(10); __e_acsl_assert(f10 == -2,1,"Assertion","main","f10 == -2", - "tests/constructs/decrease.i",63); + "tests/constructs/decrease.c",77); /*@ assert f10 ≡ -2; */ ; int f7 = f(7); __e_acsl_assert(f7 == -1,1,"Assertion","main","f7 == -1", - "tests/constructs/decrease.i",65); + "tests/constructs/decrease.c",79); /*@ assert f7 ≡ -1; */ ; int g10 = g(10); __e_acsl_assert(g10 == -2,1,"Assertion","main","g10 == -2", - "tests/constructs/decrease.i",67); + "tests/constructs/decrease.c",81); /*@ assert g10 ≡ -2; */ ; int g7 = g(7); __e_acsl_assert(g7 == -1,1,"Assertion","main","g7 == -1", - "tests/constructs/decrease.i",69); + "tests/constructs/decrease.c",83); /*@ assert g7 ≡ -1; */ ; int fact7 = __gen_e_acsl_fact(7); __e_acsl_assert(fact7 == 5040,1,"Assertion","main","fact7 == 5040", - "tests/constructs/decrease.i",72); + "tests/constructs/decrease.c",86); /*@ assert fact7 ≡ 5040; */ ; + size_t fact18 = __gen_e_acsl_fact2((unsigned long)18); + __e_acsl_assert(fact18 == 6402373705728000UL,1,"Assertion","main", + "fact18 == 6402373705728000UL", + "tests/constructs/decrease.c",89); + /*@ assert fact18 ≡ 6402373705728000UL; */ ; int fib7 = __gen_e_acsl_fib(7); __e_acsl_assert(fib7 == 13,1,"Assertion","main","fib7 == 13", - "tests/constructs/decrease.i",75); + "tests/constructs/decrease.c",92); /*@ assert fib7 ≡ 13; */ ; int even7 = __gen_e_acsl_even(7); __e_acsl_assert(even7 == 0,1,"Assertion","main","even7 == 0", - "tests/constructs/decrease.i",78); + "tests/constructs/decrease.c",95); /*@ assert even7 ≡ 0; */ ; int even10 = __gen_e_acsl_even(10); __e_acsl_assert(even10 == 1,1,"Assertion","main","even10 == 1", - "tests/constructs/decrease.i",80); + "tests/constructs/decrease.c",97); /*@ assert even10 ≡ 1; */ ; int odd7 = __gen_e_acsl_odd(7); __e_acsl_assert(odd7 == 1,1,"Assertion","main","odd7 == 1", - "tests/constructs/decrease.i",82); + "tests/constructs/decrease.c",99); /*@ assert odd7 ≡ 1; */ ; int odd10 = __gen_e_acsl_odd(10); __e_acsl_assert(odd10 == 0,1,"Assertion","main","odd10 == 0", - "tests/constructs/decrease.i",84); + "tests/constructs/decrease.c",101); /*@ assert odd10 ≡ 0; */ ; __retres = 0; return __retres; @@ -180,7 +217,7 @@ int __gen_e_acsl_even(int n) { int __retres; __e_acsl_assert(n >= 0,1,"Precondition","even","n >= 0", - "tests/constructs/decrease.i",48); + "tests/constructs/decrease.c",62); __retres = even(n); return __retres; } @@ -191,7 +228,7 @@ int __gen_e_acsl_odd(int n) { int __retres; __e_acsl_assert(n >= 0,1,"Precondition","odd","n >= 0", - "tests/constructs/decrease.i",54); + "tests/constructs/decrease.c",68); __retres = odd(n); return __retres; } @@ -204,12 +241,22 @@ int __gen_e_acsl_fib(int n) return __retres; } +/*@ requires n ≤ 20; */ +size_t __gen_e_acsl_fact2(size_t n) +{ + size_t __retres; + __e_acsl_assert(n <= 20UL,1,"Precondition","fact2","n <= 20", + "tests/constructs/decrease.c",41); + __retres = fact2(n); + return __retres; +} + /*@ requires n ≤ 12; */ int __gen_e_acsl_fact(int n) { int __retres; __e_acsl_assert(n <= 12,1,"Precondition","fact","n <= 12", - "tests/constructs/decrease.i",26); + "tests/constructs/decrease.c",28); __retres = fact(n); return __retres; } diff --git a/src/plugins/wp/Changelog b/src/plugins/wp/Changelog index afef9d75caeb521a6391a36bfd4edc1ed8879b73..21944be46f3999616ea7d7a829deae9225d730fc 100644 --- a/src/plugins/wp/Changelog +++ b/src/plugins/wp/Changelog @@ -24,6 +24,11 @@ Plugin WP <next-release> ######################### + +######################### +Plugin WP 23.1 (Vanadium) +######################### + - WP [2021-06-11] Adds an experimental support of "terminates" clauses. Adds the options -wp-declaration-terminate and -wp-frama-c-stdlib to claims that external functions @@ -37,6 +42,7 @@ Plugin WP <next-release> option -wp-smoke-dead-assumes - TIP [2021-05-31] Generalized Overflow tactic +- WP [2021-07-15] Fix a crash related to opaque structures memory typing ######################### Plugin WP 23.0 (Vanadium) diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml index abf67a6cb7c4af3ce67261a735ecfe22503268ff..5e19be9715d051d8624679c28e4046d669481044 100644 --- a/src/plugins/wp/MemTyped.ml +++ b/src/plugins/wp/MemTyped.ml @@ -118,7 +118,6 @@ let pointer = Context.create "MemTyped.pointer" type chunk = | M_int of Ctypes.c_int - | M_char | M_f32 | M_f64 | M_pointer @@ -141,7 +140,6 @@ struct | SInt64 -> 8 let rank = function - | M_char -> -1 | M_int i -> int_rank i | M_f32 -> 9 | M_f64 -> 10 @@ -150,8 +148,8 @@ struct | T_init -> 13 let hash = rank let name = function + | M_int i when Ctypes.is_char i -> "Mchar" | M_int _ -> "Mint" - | M_char -> "Mchar" | M_f32 -> "Mf32" | M_f64 -> "Mf64" | M_pointer -> "Mptr" @@ -164,14 +162,14 @@ struct | M_int i -> Format.fprintf fmt "M%a" Ctypes.pp_int i | m -> Format.pp_print_string fmt (name m) let val_of_chunk = function - | M_int _ | M_char -> L.Int + | M_int _ -> L.Int | M_f32 -> Cfloat.tau_of_float Ctypes.Float32 | M_f64 -> Cfloat.tau_of_float Ctypes.Float64 | M_pointer -> t_addr | T_alloc -> L.Int | T_init -> L.Bool let tau_of_chunk = function - | M_int _ | M_char -> L.Array(t_addr,L.Int) + | M_int _ -> L.Array(t_addr,L.Int) | M_pointer -> L.Array(t_addr,t_addr) | M_f32 -> L.Array(t_addr,Cfloat.tau_of_float Ctypes.Float32) | M_f64 -> L.Array(t_addr,Cfloat.tau_of_float Ctypes.Float64) @@ -190,11 +188,10 @@ type loc = term (* of type addr *) (* --- Utilities on locations --- *) (* -------------------------------------------------------------------------- *) -let m_int i = if Ctypes.is_char i then M_char else M_int i let m_float = function Float32 -> M_f32 | Float64 -> M_f64 let rec footprint = function - | C_int i -> Heap.Set.singleton (m_int i) + | C_int i -> Heap.Set.singleton (M_int i) | C_float f -> Heap.Set.singleton (m_float f) | C_pointer _ -> Heap.Set.singleton M_pointer | C_array a -> footprint (object_of a.arr_element) @@ -215,7 +212,7 @@ and all_value_chunks () = [ Ctypes.CBool ; SInt8 ; UInt8 ; SInt16 ; UInt16 ; SInt32 ; UInt32 ; SInt64 ; UInt64 ] in - Heap.Set.of_list (M_pointer :: M_char :: M_f32 :: M_f64 :: ints) + Heap.Set.of_list (M_pointer :: M_f32 :: M_f64 :: ints) let init_footprint _ _ = Heap.Set.singleton T_init let value_footprint obj _l = footprint obj @@ -482,8 +479,10 @@ module STRING = WpContext.Generator(LITERAL) let name = prefix ^ "_literal" in let i = Lang.freshvar ~basename:"i" L.Int in let c = Cstring.char_at cst (e_var i) in - let addr = shift (a_global base) (C_int (Ctypes.c_char ())) (e_var i) in - let m = Lang.freshvar ~basename:"mchar" (Chunk.tau_of_chunk M_char) in + let ikind = Ctypes.c_char () in + let addr = shift (a_global base) (C_int ikind) (e_var i) in + let m = + Lang.freshvar ~basename:"mchar" (Chunk.tau_of_chunk (M_int ikind)) in let m_sconst = F.p_call p_sconst [e_var m] in let v = F.e_get (e_var m) addr in let read = F.p_equal c v in @@ -980,7 +979,6 @@ module ChunkContent = WpContext.Generator(Chunk) type data = lfun let int_kind = function - | M_char -> Ctypes.c_char () | M_int k -> k | _ -> failwith "MemTyped asked constraint for non int type" @@ -1005,7 +1003,7 @@ module ChunkContent = WpContext.Generator(Chunk) end) let is_chunk sigma = function - | M_int _ | M_char as m -> + | M_int _ as m -> F.p_call (ChunkContent.get m) [ Sigma.value sigma m ] | _ -> p_true @@ -1034,7 +1032,7 @@ struct let to_region_pointer l = 0,l let of_region_pointer _ _ l = l - let load_int sigma i l = F.e_get (Sigma.value sigma (m_int i)) l + let load_int sigma i l = F.e_get (Sigma.value sigma (M_int i)) l let load_float sigma f l = F.e_get (Sigma.value sigma (m_float f)) l let load_pointer sigma _t l = F.e_get (Sigma.value sigma M_pointer) l @@ -1061,7 +1059,7 @@ struct let updated sigma c l v = c , F.e_set (Sigma.value sigma c) l v - let store_int sigma i l v = updated sigma (m_int i) l v + let store_int sigma i l v = updated sigma (M_int i) l v let store_float sigma f l v = updated sigma (m_float f) l v let store_pointer sigma _ty l v = updated sigma M_pointer l v @@ -1156,7 +1154,7 @@ let frame sigma = in wellformed_frame p_linked T_alloc @ wellformed_frame p_cinits T_init @ - wellformed_frame p_sconst M_char @ + wellformed_frame p_sconst (M_int (Ctypes.c_char ())) @ wellformed_frame p_framed M_pointer let alloc sigma xs = diff --git a/src/plugins/wp/tests/wp_acsl/opaque_struct.i b/src/plugins/wp/tests/wp_acsl/opaque_struct.i index c1e457182f2950047598a6d1005b47d07461e5da..40b9c7626f9f91ebffc6aa1c616967458e73b3c0 100644 --- a/src/plugins/wp/tests/wp_acsl/opaque_struct.i +++ b/src/plugins/wp/tests/wp_acsl/opaque_struct.i @@ -1,3 +1,10 @@ +/* run.config + OPT: -wp-rte +*/ +/* run.config_qualif + OPT: -wp-rte +*/ + struct S; extern struct S S1; @@ -63,3 +70,14 @@ void assigns_effect(int* p, float* q, char* c, struct S *a){ //@ check fail: *q == \at(*q, Pre); //@ check succeed: *c == \at(*c, Pre); } + +// regression on MemTyped chunk typing + +void use(struct S * s); + +//@ requires \valid(uc) && \valid_read(sc) ; +void chunk_typing(unsigned char* uc, signed char* sc){ + struct S* s ; + *uc = *sc ; + use(s) ; +} diff --git a/src/plugins/wp/tests/wp_acsl/oracle/opaque_struct.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/opaque_struct.res.oracle index 519985dbf06721b87bb7f9823c5b53859268672c..ea7df3161832b757ba0905c7e57c740a8f29742a 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle/opaque_struct.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle/opaque_struct.res.oracle @@ -1,7 +1,14 @@ -# frama-c -wp [...] +# frama-c -wp -wp-rte [...] [kernel] Parsing tests/wp_acsl/opaque_struct.i (no preprocessing) [wp] Running WP plugin... -[wp] Warning: Missing RTE guards +[rte] annotating function assigned_via_pointer +[rte] annotating function assigns +[rte] annotating function assigns_effect +[rte] annotating function chunk_typing +[rte] annotating function initialized_assigns +[rte] annotating function uninitialized_assigns +[kernel:annot:missing-spec] tests/wp_acsl/opaque_struct.i:79: Warning: + Neither code nor specification for function use, generating default assigns from the prototype ------------------------------------------------------------ Axiomatic 'test' ------------------------------------------------------------ @@ -24,38 +31,46 @@ Prove: 0<=BytesLength_of_S1_S Function assigned_via_pointer ------------------------------------------------------------ -Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 53): +Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 60): +Let a = havoc(Mint_undef_0, Mint_0, p, Length_of_S1_S). +Let a_1 = havoc(Mint_undef_3, Mint_3, p, Length_of_S1_S). +Let a_2 = havoc(Mint_undef_5, Mint_5, p, Length_of_S1_S). +Let a_3 = havoc(Mint_undef_7, Mint_7, p, Length_of_S1_S). +Let a_4 = havoc(Mchar_undef_0, Mchar_0, p, Length_of_S1_S). +Let a_5 = havoc(Mint_undef_2, Mint_2, p, Length_of_S1_S). +Let a_6 = havoc(Mint_undef_4, Mint_4, p, Length_of_S1_S). +Let a_7 = havoc(Mint_undef_6, Mint_6, p, Length_of_S1_S). +Let a_8 = havoc(Mint_undef_1, Mint_1, p, Length_of_S1_S). Assume { + Type: is_bool_chunk(Mint_0) /\ is_sint16_chunk(Mint_3) /\ + is_sint32_chunk(Mint_5) /\ is_sint64_chunk(Mint_7) /\ + is_sint8_chunk(Mchar_0) /\ is_uint16_chunk(Mint_2) /\ + is_uint32_chunk(Mint_4) /\ is_uint64_chunk(Mint_6) /\ + is_uint8_chunk(Mint_1) /\ is_bool_chunk(a) /\ is_sint16_chunk(a_1) /\ + is_sint32_chunk(a_2) /\ is_sint64_chunk(a_3) /\ is_sint8_chunk(a_4) /\ + is_uint16_chunk(a_5) /\ is_uint32_chunk(a_6) /\ is_uint64_chunk(a_7) /\ + is_uint8_chunk(a_8). (* Heap *) Type: (region(p.base) <= 0) /\ framed(Mptr_0) /\ sconst(Mchar_0). } -Prove: EqS1_S(Load_S1_S(p, havoc(Mchar_undef_0, Mchar_0, p, Length_of_S1_S), - havoc(Mint_undef_0, Mint_0, p, Length_of_S1_S), - havoc(Mint_undef_1, Mint_1, p, Length_of_S1_S), - havoc(Mint_undef_2, Mint_2, p, Length_of_S1_S), - havoc(Mint_undef_3, Mint_3, p, Length_of_S1_S), - havoc(Mint_undef_4, Mint_4, p, Length_of_S1_S), - havoc(Mint_undef_5, Mint_5, p, Length_of_S1_S), - havoc(Mint_undef_6, Mint_6, p, Length_of_S1_S), - havoc(Mint_undef_7, Mint_7, p, Length_of_S1_S), - havoc(Mint_undef_8, Mint_8, p, Length_of_S1_S), +Prove: EqS1_S(Load_S1_S(p, a, a_8, a_4, a_5, a_1, a_6, a_2, a_7, a_3, havoc(Mf32_undef_0, Mf32_0, p, Length_of_S1_S), havoc(Mf64_undef_0, Mf64_0, p, Length_of_S1_S), havoc(Mptr_undef_0, Mptr_0, p, Length_of_S1_S)), - Load_S1_S(p, Mchar_0, Mint_0, Mint_1, Mint_2, Mint_3, Mint_4, - Mint_5, Mint_6, Mint_7, Mint_8, Mf32_0, Mf64_0, Mptr_0)). + Load_S1_S(p, Mint_0, Mint_1, Mchar_0, Mint_2, Mint_3, Mint_4, + Mint_5, Mint_6, Mint_7, Mf32_0, Mf64_0, Mptr_0)). ------------------------------------------------------------ ------------------------------------------------------------ Function assigns ------------------------------------------------------------ -Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 17): +Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 24): Prove: EqS1_S(S1_0, S1_1). ------------------------------------------------------------ -Goal Check 'succeed' (file tests/wp_acsl/opaque_struct.i, line 18): +Goal Check 'succeed' (file tests/wp_acsl/opaque_struct.i, line 25): Prove: true. ------------------------------------------------------------ @@ -63,22 +78,24 @@ Prove: true. Function assigns_effect ------------------------------------------------------------ -Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 62): +Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 69): Let x = Mint_0[p]. -Let a_1 = havoc(Mint_undef_0, Mint_0, a, Length_of_S1_S)[p]. +Let a_1 = havoc(Mint_undef_0, Mint_0, a, Length_of_S1_S). +Let a_2 = a_1[p]. Assume { - Type: is_sint32(x) /\ is_sint32(a_1). + Type: is_sint32_chunk(Mint_0) /\ is_sint32(x) /\ is_sint32_chunk(a_1) /\ + is_sint32(a_2). (* Heap *) Type: (region(a.base) <= 0) /\ (region(c.base) <= 0) /\ (region(p.base) <= 0). (* Pre-condition *) Have: separated(a, Length_of_S1_S, c, 1). } -Prove: a_1 = x. +Prove: a_2 = x. ------------------------------------------------------------ -Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 63): +Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 70): Assume { (* Heap *) Type: (region(a.base) <= 0) /\ (region(c.base) <= 0) /\ @@ -91,24 +108,39 @@ Prove: of_f32(havoc(Mf32_undef_0, Mf32_0, a, Length_of_S1_S)[q]) ------------------------------------------------------------ -Goal Check 'succeed' (file tests/wp_acsl/opaque_struct.i, line 64): +Goal Check 'succeed' (file tests/wp_acsl/opaque_struct.i, line 71): Let x = Mchar_0[c]. -Let a_1 = havoc(Mchar_undef_0, Mchar_0, a, Length_of_S1_S)[c]. +Let a_1 = havoc(Mchar_undef_0, Mchar_0, a, Length_of_S1_S). +Let a_2 = a_1[c]. Assume { - Type: is_sint8(x) /\ is_sint8(a_1). + Type: is_sint8_chunk(Mchar_0) /\ is_sint8(x) /\ is_sint8_chunk(a_1) /\ + is_sint8(a_2). (* Heap *) Type: (region(a.base) <= 0) /\ (region(c.base) <= 0) /\ sconst(Mchar_0). (* Pre-condition *) Have: separated(a, Length_of_S1_S, c, 1). } -Prove: a_1 = x. +Prove: a_2 = x. + +------------------------------------------------------------ +------------------------------------------------------------ + Function chunk_typing +------------------------------------------------------------ + +Goal Assertion 'rte,mem_access' (file tests/wp_acsl/opaque_struct.i, line 81): +Prove: true. + +------------------------------------------------------------ + +Goal Assertion 'rte,mem_access' (file tests/wp_acsl/opaque_struct.i, line 81): +Prove: true. ------------------------------------------------------------ ------------------------------------------------------------ Function initialized_assigns ------------------------------------------------------------ -Goal Check 'fails' (file tests/wp_acsl/opaque_struct.i, line 31): +Goal Check 'fails' (file tests/wp_acsl/opaque_struct.i, line 38): Let a = havoc(Init_undef_0, Init_0, p, Length_of_S1_S). Assume { (* Heap *) @@ -124,7 +156,7 @@ Prove: IsInit_S1_S(p, a). ------------------------------------------------------------ -Goal Check 'succeed' (file tests/wp_acsl/opaque_struct.i, line 32): +Goal Check 'succeed' (file tests/wp_acsl/opaque_struct.i, line 39): Let x = p.base. Assume { (* Heap *) @@ -139,7 +171,7 @@ Prove: 0 <= (BytesLength_of_S1_S * (Malloc_0[x] / Length_of_S1_S)). Function uninitialized_assigns ------------------------------------------------------------ -Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 47): +Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 54): Let a = havoc(Init_undef_0, Init_0, p, Length_of_S1_S). Assume { (* Heap *) @@ -153,7 +185,7 @@ Prove: !IsInit_S1_S(p, a). ------------------------------------------------------------ -Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 48): +Goal Check 'fail' (file tests/wp_acsl/opaque_struct.i, line 55): Let a = havoc(Init_undef_0, Init_0, p, Length_of_S1_S). Assume { (* Heap *) @@ -166,17 +198,17 @@ Assume { Prove: IsInit_S1_S(p, a). ------------------------------------------------------------ -[wp] tests/wp_acsl/opaque_struct.i:24: Warning: +[wp] tests/wp_acsl/opaque_struct.i:31: Warning: Memory model hypotheses for function 'g': /*@ behavior wp_typed: requires \separated(p, &S1, &S2, &p); */ void g(void); -[wp] tests/wp_acsl/opaque_struct.i:57: Warning: +[wp] tests/wp_acsl/opaque_struct.i:64: Warning: Memory model hypotheses for function 'assign': /*@ behavior wp_typed: requires \separated(a, &S1, &S2); */ void assign(struct S *a); -[wp] tests/wp_acsl/opaque_struct.i:60: Warning: +[wp] tests/wp_acsl/opaque_struct.i:67: Warning: Memory model hypotheses for function 'assigns_effect': /*@ behavior wp_typed: @@ -186,3 +218,16 @@ Prove: IsInit_S1_S(p, a). requires \separated(q, &S1, &S2); */ void assigns_effect(int *p_0, float *q, char *c, struct S *a); +[wp] tests/wp_acsl/opaque_struct.i:76: Warning: + Memory model hypotheses for function 'use': + /*@ behavior wp_typed: + requires \separated(s, &S1, &S2); */ + void use(struct S *s); +[wp] tests/wp_acsl/opaque_struct.i:79: Warning: + Memory model hypotheses for function 'chunk_typing': + /*@ + behavior wp_typed: + requires \separated(sc, &S1, &S2); + requires \separated(uc, &S1, &S2); + */ + void chunk_typing(unsigned char *uc, signed char *sc); diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/opaque_struct.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/opaque_struct.res.oracle index ffca345397b95ff7963379b5e563fc3f6d562997..de7c9982adaecd3927eab97cd49cfebb8fc33069 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/opaque_struct.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/opaque_struct.res.oracle @@ -1,8 +1,15 @@ -# frama-c -wp [...] +# frama-c -wp -wp-rte [...] [kernel] Parsing tests/wp_acsl/opaque_struct.i (no preprocessing) [wp] Running WP plugin... -[wp] Warning: Missing RTE guards -[wp] 13 goals scheduled +[rte] annotating function assigned_via_pointer +[rte] annotating function assigns +[rte] annotating function assigns_effect +[rte] annotating function chunk_typing +[rte] annotating function initialized_assigns +[rte] annotating function uninitialized_assigns +[kernel:annot:missing-spec] tests/wp_acsl/opaque_struct.i:79: Warning: + Neither code nor specification for function use, generating default assigns from the prototype +[wp] 15 goals scheduled [wp] [Alt-Ergo] Goal typed_check_lemma_fail : Unsuccess [wp] [Qed] Goal typed_check_lemma_succeed_L1 : Valid [wp] [Alt-Ergo] Goal typed_check_lemma_succeed_L2 : Valid @@ -16,8 +23,10 @@ [wp] [Alt-Ergo] Goal typed_assigns_effect_check_fail : Unsuccess [wp] [Alt-Ergo] Goal typed_assigns_effect_check_fail_2 : Unsuccess [wp] [Alt-Ergo] Goal typed_assigns_effect_check_succeed : Valid -[wp] Proved goals: 5 / 13 - Qed: 2 +[wp] [Qed] Goal typed_chunk_typing_assert_rte_mem_access : Valid +[wp] [Qed] Goal typed_chunk_typing_assert_rte_mem_access_2 : Valid +[wp] Proved goals: 7 / 15 + Qed: 4 Alt-Ergo: 3 (unsuccess: 8) ------------------------------------------------------------ Axiomatics WP Alt-Ergo Total Success @@ -29,18 +38,19 @@ uninitialized_assigns - - 2 0.0% assigned_via_pointer - - 1 0.0% assigns_effect - 1 3 33.3% + chunk_typing 2 - 2 100% ------------------------------------------------------------ -[wp] tests/wp_acsl/opaque_struct.i:24: Warning: +[wp] tests/wp_acsl/opaque_struct.i:31: Warning: Memory model hypotheses for function 'g': /*@ behavior wp_typed: requires \separated(p, &S1, &S2, &p); */ void g(void); -[wp] tests/wp_acsl/opaque_struct.i:57: Warning: +[wp] tests/wp_acsl/opaque_struct.i:64: Warning: Memory model hypotheses for function 'assign': /*@ behavior wp_typed: requires \separated(a, &S1, &S2); */ void assign(struct S *a); -[wp] tests/wp_acsl/opaque_struct.i:60: Warning: +[wp] tests/wp_acsl/opaque_struct.i:67: Warning: Memory model hypotheses for function 'assigns_effect': /*@ behavior wp_typed: @@ -50,3 +60,16 @@ requires \separated(q, &S1, &S2); */ void assigns_effect(int *p_0, float *q, char *c, struct S *a); +[wp] tests/wp_acsl/opaque_struct.i:76: Warning: + Memory model hypotheses for function 'use': + /*@ behavior wp_typed: + requires \separated(s, &S1, &S2); */ + void use(struct S *s); +[wp] tests/wp_acsl/opaque_struct.i:79: Warning: + Memory model hypotheses for function 'chunk_typing': + /*@ + behavior wp_typed: + requires \separated(sc, &S1, &S2); + requires \separated(uc, &S1, &S2); + */ + void chunk_typing(unsigned char *uc, signed char *sc);