From 35d900faa860ee1f083d5018352871f12d8fe98d Mon Sep 17 00:00:00 2001
From: Basile Desloges <basile.desloges@cea.fr>
Date: Tue, 6 Oct 2020 10:52:44 +0200
Subject: [PATCH] [eacsl:codegen] Fix soundness bug when translating a range
 with a logic variable

---
 src/plugins/e-acsl/src/analyses/typing.ml                 | 2 +-
 src/plugins/e-acsl/src/analyses/typing.mli                | 7 +++++--
 src/plugins/e-acsl/src/code_generator/memory_translate.ml | 2 +-
 src/plugins/e-acsl/src/code_generator/translate.ml        | 5 +++++
 src/plugins/e-acsl/tests/memory/ranges_in_builtins.c      | 3 +++
 5 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/plugins/e-acsl/src/analyses/typing.ml b/src/plugins/e-acsl/src/analyses/typing.ml
index e413aea96d1..df114cc3a82 100644
--- a/src/plugins/e-acsl/src/analyses/typing.ml
+++ b/src/plugins/e-acsl/src/analyses/typing.ml
@@ -707,7 +707,7 @@ let type_term ~use_gmp_opt ?ctx t =
     Printer.pp_term t (Pretty_utils.pp_opt D.pretty) ctx;
   ignore (type_term ~use_gmp_opt ?ctx t)
 
-let type_named_predicate ?(must_clear=true) p =
+let type_named_predicate ~must_clear p =
   Options.feedback ~dkey ~level:3 "typing predicate '%a'."
     Printer.pp_predicate p;
   if must_clear then begin
diff --git a/src/plugins/e-acsl/src/analyses/typing.mli b/src/plugins/e-acsl/src/analyses/typing.mli
index 7a7fd0f80d5..c35a8e81952 100644
--- a/src/plugins/e-acsl/src/analyses/typing.mli
+++ b/src/plugins/e-acsl/src/analyses/typing.mli
@@ -101,9 +101,12 @@ val type_term: use_gmp_opt:bool -> ?ctx:number_ty -> term -> unit
     [use_gmp_opt] is false, then the conversion to the given context is done
     even if -e-acsl-gmp-only is set. *)
 
-val type_named_predicate: ?must_clear:bool -> predicate -> unit
+val type_named_predicate: must_clear:bool -> predicate -> unit
 (** Compute the type of each term of the given predicate.
-    Set {!must_clear} to false in order to not reset the environment. *)
+
+    If {!must_clear} is true, the typing environment is reset before translating
+    the predicate. The environment should be reset when translating a new
+    assertion, and kept otherwise. *)
 
 val clear: unit -> unit
 (** Remove all the previously computed types. *)
diff --git a/src/plugins/e-acsl/src/code_generator/memory_translate.ml b/src/plugins/e-acsl/src/code_generator/memory_translate.ml
index 2b496a89f87..f691e41ca97 100644
--- a/src/plugins/e-acsl/src/code_generator/memory_translate.ml
+++ b/src/plugins/e-acsl/src/code_generator/memory_translate.ml
@@ -420,7 +420,7 @@ let call_with_tset ~loc ~arg_from_range ~arg_from_term ?(prepend_n_args=false) k
     in
     (* There's no more quantifiers in the arguments now, we can call back
        [prediate_to_exp] to translate the predicate as usual *)
-    Typing.type_named_predicate ~must_clear:true p_quantified;
+    Typing.type_named_predicate ~must_clear:false p_quantified;
     !predicate_to_exp_ref kf env p_quantified
   | [] ->
     (* No arguments require quantifiers, so we can directly translate the
diff --git a/src/plugins/e-acsl/src/code_generator/translate.ml b/src/plugins/e-acsl/src/code_generator/translate.ml
index 860c165a18a..9ad2815d009 100644
--- a/src/plugins/e-acsl/src/code_generator/translate.ml
+++ b/src/plugins/e-acsl/src/code_generator/translate.ml
@@ -1050,6 +1050,11 @@ and predicate_to_exp ?name kf ?rte env p =
     e
 
 and generalized_untyped_predicate_to_exp ?name kf ?rte ?must_clear_typing env p =
+  (* If [rte] is true, it means we're translating the root predicate of an
+     assertion and we need to generate the RTE for it. The typing environment
+     must be cleared. Otherwise, if [rte] is false, it means we're already
+     translating RTE predicates as part of the translation of another root
+     predicate, and the typing environment must be kept. *)
   let rte = match rte with None -> Env.generate_rte env | Some b -> b in
   let must_clear = match must_clear_typing with None -> rte | Some b -> b in
   Typing.type_named_predicate ~must_clear p;
diff --git a/src/plugins/e-acsl/tests/memory/ranges_in_builtins.c b/src/plugins/e-acsl/tests/memory/ranges_in_builtins.c
index 4cb9d45b44a..7af22946ecf 100644
--- a/src/plugins/e-acsl/tests/memory/ranges_in_builtins.c
+++ b/src/plugins/e-acsl/tests/memory/ranges_in_builtins.c
@@ -48,6 +48,9 @@ int main(void) {
   /*@ assert !\valid_read(&t3[6][1][0] + (2..10)); */
   /*@ assert \valid_read(&t3[(n-1)..(n+2)][1]); */
 
+  int t4[10][10][10];
+  /*@ assert \let x = 5; \valid(&t4[4][0..x][2]); */
+
   struct S s;
   s.a[0] = 7; s.a[1] = 8;
   /*@ assert \initialized(&s.a[0] + (1..1)); */ ;
-- 
GitLab