From bfb9f650f030fe8dfffa09683dd821b40a586c19 Mon Sep 17 00:00:00 2001
From: Julien Signoles <julien.signoles@cea.fr>
Date: Tue, 7 May 2013 13:24:32 +0000
Subject: [PATCH] [E-ACSL] analysis: fixed bug in presence of an alias with an
 explicit address

---
 .../e-acsl/known_bugs/taking_address.i        |  7 ---
 src/plugins/e-acsl/pre_analysis.ml            | 27 +++++++++--
 .../e-acsl/tests/e-acsl-runtime/addrOf.i      |  9 ++++
 .../e-acsl-runtime/oracle/addrOf.1.res.oracle | 14 +++++-
 .../e-acsl-runtime/oracle/addrOf.res.oracle   | 14 +++++-
 .../tests/e-acsl-runtime/oracle/gen_addrOf.c  | 48 ++++++++++++++++++-
 .../tests/e-acsl-runtime/oracle/gen_addrOf2.c | 48 ++++++++++++++++++-
 .../e-acsl-runtime/oracle/gen_localvar.c      |  6 +++
 .../e-acsl-runtime/oracle/gen_localvar2.c     |  6 +++
 .../tests/e-acsl-runtime/oracle/gen_ptr.c     |  1 +
 .../tests/e-acsl-runtime/oracle/gen_ptr2.c    |  1 +
 .../oracle/localvar.1.res.oracle              |  1 +
 .../e-acsl-runtime/oracle/localvar.res.oracle |  1 +
 13 files changed, 168 insertions(+), 15 deletions(-)
 delete mode 100644 src/plugins/e-acsl/known_bugs/taking_address.i

diff --git a/src/plugins/e-acsl/known_bugs/taking_address.i b/src/plugins/e-acsl/known_bugs/taking_address.i
deleted file mode 100644
index 4122f697546..00000000000
--- a/src/plugins/e-acsl/known_bugs/taking_address.i
+++ /dev/null
@@ -1,7 +0,0 @@
-int main(){
-  int m, *u, *p;
-  u = &m;
-  p = u;
-  m = 123;
-  //@ assert \initialized(p);
-}
diff --git a/src/plugins/e-acsl/pre_analysis.ml b/src/plugins/e-acsl/pre_analysis.ml
index f2b9c3db37f..68594cbad3b 100644
--- a/src/plugins/e-acsl/pre_analysis.ml
+++ b/src/plugins/e-acsl/pre_analysis.ml
@@ -367,7 +367,22 @@ module rec Transfer
 	| Some vi -> add_vi state vi
     in
     match instr with
-    | Set((lhost, _), e, _) -> 
+    | Set((lhost, _) as lv, e, _) -> 
+      (* if [e]  contains an address from a base to be monitored, then also
+	 monitor the host *)
+      let rec extend_from_addr state e = match e.enode with
+	| AddrOf(lhost, _) -> 
+	  extend_to_expr state lhost (Cil.new_exp ~loc:e.eloc (Lval lv))
+	| BinOp((PlusPI | IndexPI | MinusPI), e1, e2, _) -> 
+	  if is_ptr_or_array_exp e1 then extend_from_addr state e1
+	  else begin
+	    assert (is_ptr_or_array_exp e2);
+	    extend_from_addr state e2
+	  end
+	| CastE(_, e) | Info(e, _) -> extend_from_addr state e
+	| _ -> state
+      in
+      let state = extend_from_addr state e in
       Dataflow.Done (Some (extend_to_expr state lhost e))
     | Call(result, f_exp, l, _) -> 
       (match f_exp.enode with
@@ -526,11 +541,15 @@ instrumentation.";
   end
 
 let must_model_vi ?kf ?stmt vi =
-  let kf = match kf, stmt with
+  let _kf = match kf, stmt with
     | None, None | Some _, _ -> kf
     | None, Some stmt -> Some (Kernel_function.find_englobing_kf stmt)
   in
-  match stmt, kf with
+  (* [JS 2013/05/07] that is unsound to take the env from the given stmt in
+     presence of aliasing with an address (see tests address.i).
+     TODO: could be optimized though *)
+  consolidated_must_model_vi vi
+(*  match stmt, kf with
   | None, _ -> consolidated_must_model_vi vi
   | Some _, None ->
     assert false
@@ -548,7 +567,7 @@ let must_model_vi ?kf ?stmt vi =
     with Not_found -> 
       (* [kf] is dead code *)
       false
-
+ *)
 let rec must_model_lval ?kf ?stmt = function
   | Var vi, _ -> must_model_vi ?kf ?stmt vi
   | Mem e, _ -> must_model_exp ?kf ?stmt e
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/addrOf.i b/src/plugins/e-acsl/tests/e-acsl-runtime/addrOf.i
index 60fd3c341f8..8436ac41c09 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/addrOf.i
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/addrOf.i
@@ -4,8 +4,17 @@
    EXECNOW: LOG gen_addrOf2.c BIN gen_addrOf2.out @frama-c@ -e-acsl-share ./share/e-acsl ./tests/e-acsl-runtime/addrOf.i -e-acsl-gmp-only -e-acsl -then-on e-acsl -print -ocode ./tests/e-acsl-runtime/result/gen_addrOf2.c > /dev/null && ./gcc_test.sh addrOf2
 */
 
+void f(){
+  int m, *u, *p;
+  u = &m;
+  p = u;
+  m = 123;
+  //@ assert \initialized(p);
+}
+
 int main(void) {
   int x = 0;
+  f();
   /*@ assert &x == &x; */ ;
   return 0;
 }
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.1.res.oracle b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.1.res.oracle
index 710876048c4..28d84b4bdc5 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.1.res.oracle
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.1.res.oracle
@@ -14,13 +14,25 @@
   __fc_rand_max ∈ {32767}
   __fc_heap_status ∈ [--..--]
   __memory_size ∈ [--..--]
-tests/e-acsl-runtime/addrOf.i:9:[value] Assertion got status valid.
+[value] using specification for function __store_block
+[value] using specification for function __full_init
+tests/e-acsl-runtime/addrOf.i:12:[value] Assertion got status valid.
+[value] using specification for function __initialized
+share/e-acsl/memory_model/e_acsl_mmodel.h:86:[value] Function __initialized: postcondition got status unknown.
+share/e-acsl/memory_model/e_acsl_mmodel.h:87:[value] Function __initialized: postcondition got status valid.
 [value] using specification for function e_acsl_assert
+share/e-acsl/e_acsl.h:34:[value] Function e_acsl_assert: precondition got status unknown.
+[value] using specification for function __delete_block
+tests/e-acsl-runtime/addrOf.i:18:[value] Assertion got status valid.
 share/e-acsl/e_acsl.h:34:[value] Function e_acsl_assert: precondition got status valid.
 [kernel] warning: Neither code nor specification for function __clean, generating default assigns from the prototype
 [value] using specification for function __clean
 [value] done for function main
 [value] ====== VALUES COMPUTED ======
+[value] Values at end of function f:
+  m ∈ {123}
+  u ∈ {{ &m }}
+  p ∈ {{ &m }}
 [value] Values at end of function main:
   x ∈ {0}
   __retres ∈ {0}
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.res.oracle b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.res.oracle
index 710876048c4..28d84b4bdc5 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.res.oracle
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/addrOf.res.oracle
@@ -14,13 +14,25 @@
   __fc_rand_max ∈ {32767}
   __fc_heap_status ∈ [--..--]
   __memory_size ∈ [--..--]
-tests/e-acsl-runtime/addrOf.i:9:[value] Assertion got status valid.
+[value] using specification for function __store_block
+[value] using specification for function __full_init
+tests/e-acsl-runtime/addrOf.i:12:[value] Assertion got status valid.
+[value] using specification for function __initialized
+share/e-acsl/memory_model/e_acsl_mmodel.h:86:[value] Function __initialized: postcondition got status unknown.
+share/e-acsl/memory_model/e_acsl_mmodel.h:87:[value] Function __initialized: postcondition got status valid.
 [value] using specification for function e_acsl_assert
+share/e-acsl/e_acsl.h:34:[value] Function e_acsl_assert: precondition got status unknown.
+[value] using specification for function __delete_block
+tests/e-acsl-runtime/addrOf.i:18:[value] Assertion got status valid.
 share/e-acsl/e_acsl.h:34:[value] Function e_acsl_assert: precondition got status valid.
 [kernel] warning: Neither code nor specification for function __clean, generating default assigns from the prototype
 [value] using specification for function __clean
 [value] done for function main
 [value] ====== VALUES COMPUTED ======
+[value] Values at end of function f:
+  m ∈ {123}
+  u ∈ {{ &m }}
+  p ∈ {{ &m }}
 [value] Values at end of function main:
   x ∈ {0}
   __retres ∈ {0}
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf.c b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf.c
index 831b7db83a0..eb348beab5c 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf.c
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf.c
@@ -30,6 +30,24 @@ axiomatic
   
   }
  */
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void *__store_block(void *ptr,
+                                                            size_t size);
+
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void __delete_block(void *ptr);
+
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void __full_init(void *ptr);
+
+/*@ ensures \result ≡ 0 ∨ \result ≡ 1;
+    ensures
+      \result ≡ 1 ⇒ \initialized((char *)\old(ptr)+(0..\old(size)-1));
+    assigns \nothing;
+ */
+extern  __attribute__((__FC_BUILTIN__)) int __initialized(void *ptr,
+                                                          size_t size);
+
 extern  __attribute__((__FC_BUILTIN__)) void __clean(void);
 
 extern size_t __memory_size;
@@ -38,14 +56,42 @@ extern size_t __memory_size;
 predicate diffSize{L1, L2}(ℤ i) =
   \at(__memory_size,L1)-\at(__memory_size,L2) ≡ i;
  */
+void f(void)
+{
+  int m;
+  int *u;
+  int *p;
+  __store_block((void *)(& p),4U);
+  __store_block((void *)(& u),4U);
+  __store_block((void *)(& m),4U);
+  __full_init((void *)(& u));
+  u = & m;
+  __full_init((void *)(& p));
+  p = u;
+  __full_init((void *)(& m));
+  m = 123;
+  /*@ assert \initialized(p); */
+  {
+    int __e_acsl_initialized;
+    __e_acsl_initialized = __initialized((void *)p,sizeof(int));
+    e_acsl_assert(__e_acsl_initialized,(char *)"Assertion",(char *)"f",
+                  (char *)"\\initialized(p)",12);
+  }
+  __delete_block((void *)(& p));
+  __delete_block((void *)(& u));
+  __delete_block((void *)(& m));
+  return;
+}
+
 int main(void)
 {
   int __retres;
   int x;
   x = 0;
+  f();
   /*@ assert &x ≡ &x; */
   e_acsl_assert(& x == & x,(char *)"Assertion",(char *)"main",
-                (char *)"&x == &x",9);
+                (char *)"&x == &x",18);
   __retres = 0;
   __clean();
   return __retres;
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf2.c b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf2.c
index 831b7db83a0..eb348beab5c 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf2.c
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_addrOf2.c
@@ -30,6 +30,24 @@ axiomatic
   
   }
  */
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void *__store_block(void *ptr,
+                                                            size_t size);
+
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void __delete_block(void *ptr);
+
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void __full_init(void *ptr);
+
+/*@ ensures \result ≡ 0 ∨ \result ≡ 1;
+    ensures
+      \result ≡ 1 ⇒ \initialized((char *)\old(ptr)+(0..\old(size)-1));
+    assigns \nothing;
+ */
+extern  __attribute__((__FC_BUILTIN__)) int __initialized(void *ptr,
+                                                          size_t size);
+
 extern  __attribute__((__FC_BUILTIN__)) void __clean(void);
 
 extern size_t __memory_size;
@@ -38,14 +56,42 @@ extern size_t __memory_size;
 predicate diffSize{L1, L2}(ℤ i) =
   \at(__memory_size,L1)-\at(__memory_size,L2) ≡ i;
  */
+void f(void)
+{
+  int m;
+  int *u;
+  int *p;
+  __store_block((void *)(& p),4U);
+  __store_block((void *)(& u),4U);
+  __store_block((void *)(& m),4U);
+  __full_init((void *)(& u));
+  u = & m;
+  __full_init((void *)(& p));
+  p = u;
+  __full_init((void *)(& m));
+  m = 123;
+  /*@ assert \initialized(p); */
+  {
+    int __e_acsl_initialized;
+    __e_acsl_initialized = __initialized((void *)p,sizeof(int));
+    e_acsl_assert(__e_acsl_initialized,(char *)"Assertion",(char *)"f",
+                  (char *)"\\initialized(p)",12);
+  }
+  __delete_block((void *)(& p));
+  __delete_block((void *)(& u));
+  __delete_block((void *)(& m));
+  return;
+}
+
 int main(void)
 {
   int __retres;
   int x;
   x = 0;
+  f();
   /*@ assert &x ≡ &x; */
   e_acsl_assert(& x == & x,(char *)"Assertion",(char *)"main",
-                (char *)"&x == &x",9);
+                (char *)"&x == &x",18);
   __retres = 0;
   __clean();
   return __retres;
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar.c b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar.c
index 3e5483cb4c3..61a4f0a1f7f 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar.c
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar.c
@@ -64,6 +64,10 @@ extern  __attribute__((__FC_BUILTIN__)) void *__store_block(void *ptr,
 /*@ assigns \nothing; */
 extern  __attribute__((__FC_BUILTIN__)) void __delete_block(void *ptr);
 
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void __initialize(void *ptr,
+                                                          size_t size);
+
 /*@ assigns \nothing; */
 extern  __attribute__((__FC_BUILTIN__)) void __full_init(void *ptr);
 
@@ -138,7 +142,9 @@ struct list *add(struct list *l, int i)
     e_acsl_assert(__e_acsl_and,(char *)"Assertion",(char *)"add",
                   (char *)"\\valid(new)",20);
   }
+  __initialize((void *)(& new->element),sizeof(int));
   new->element = i;
+  __initialize((void *)(& new->next),sizeof(struct list *));
   new->next = l;
   __delete_block((void *)(& new));
   return new;
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar2.c b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar2.c
index 3e5483cb4c3..61a4f0a1f7f 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar2.c
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_localvar2.c
@@ -64,6 +64,10 @@ extern  __attribute__((__FC_BUILTIN__)) void *__store_block(void *ptr,
 /*@ assigns \nothing; */
 extern  __attribute__((__FC_BUILTIN__)) void __delete_block(void *ptr);
 
+/*@ assigns \nothing; */
+extern  __attribute__((__FC_BUILTIN__)) void __initialize(void *ptr,
+                                                          size_t size);
+
 /*@ assigns \nothing; */
 extern  __attribute__((__FC_BUILTIN__)) void __full_init(void *ptr);
 
@@ -138,7 +142,9 @@ struct list *add(struct list *l, int i)
     e_acsl_assert(__e_acsl_and,(char *)"Assertion",(char *)"add",
                   (char *)"\\valid(new)",20);
   }
+  __initialize((void *)(& new->element),sizeof(int));
   new->element = i;
+  __initialize((void *)(& new->next),sizeof(struct list *));
   new->next = l;
   __delete_block((void *)(& new));
   return new;
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr.c b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr.c
index 176208d82ad..2e767773d5d 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr.c
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr.c
@@ -148,6 +148,7 @@ int main(void)
   }
   __full_init((void *)(& p));
   p = & t[2];
+  __initialize((void *)(& t[2]),sizeof(int));
   t[2] = 5;
   /*@ assert *p ≡ 5; */
   {
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr2.c b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr2.c
index c97a4938d67..126ae683f42 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr2.c
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/gen_ptr2.c
@@ -313,6 +313,7 @@ int main(void)
   }
   __full_init((void *)(& p));
   p = & t[2];
+  __initialize((void *)(& t[2]),sizeof(int));
   t[2] = 5;
   /*@ assert *p ≡ 5; */
   {
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.1.res.oracle b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.1.res.oracle
index 2aca7b0bf65..2a590db1377 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.1.res.oracle
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.1.res.oracle
@@ -34,6 +34,7 @@ share/e-acsl/memory_model/e_acsl_mmodel.h:87:[value] Function __initialized: pos
 [value] using specification for function __valid
 [value] using specification for function e_acsl_assert
 share/e-acsl/e_acsl.h:34:[value] Function e_acsl_assert: precondition got status unknown.
+[value] using specification for function __initialize
 [kernel] warning: Neither code nor specification for function __clean, generating default assigns from the prototype
 [value] using specification for function __clean
 [value] done for function main
diff --git a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.res.oracle b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.res.oracle
index 2aca7b0bf65..2a590db1377 100644
--- a/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.res.oracle
+++ b/src/plugins/e-acsl/tests/e-acsl-runtime/oracle/localvar.res.oracle
@@ -34,6 +34,7 @@ share/e-acsl/memory_model/e_acsl_mmodel.h:87:[value] Function __initialized: pos
 [value] using specification for function __valid
 [value] using specification for function e_acsl_assert
 share/e-acsl/e_acsl.h:34:[value] Function e_acsl_assert: precondition got status unknown.
+[value] using specification for function __initialize
 [kernel] warning: Neither code nor specification for function __clean, generating default assigns from the prototype
 [value] using specification for function __clean
 [value] done for function main
-- 
GitLab