diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog
index 846b909f021aef97bbcb0761d6dceeb906f77089..fa4dbd4f4abde2c118f0def338e392cc02cc23f8 100644
--- a/src/plugins/e-acsl/doc/Changelog
+++ b/src/plugins/e-acsl/doc/Changelog
@@ -15,6 +15,8 @@
 #   E-ACSL: the Whole E-ACSL plug-in
 ###############################################################################
 
+-* E-ACSL       [2017/02/17] Fix bug with goto which points to a labeled
+	        statement which must be instrumented.
 -* E-ACSL       [2017/01/23] Fix bug #2252 about pointer arithmetic with
 	        negative offsets.
 -* E-ACSL       [2017/01/23] Fix bug with typing of unary and binary
diff --git a/src/plugins/e-acsl/label.ml b/src/plugins/e-acsl/label.ml
index 2e1cedd931c1aca6958fc52663de4e3a082d6bfe..bef275d6776f7537ecf22a1686c3af14fb687787 100644
--- a/src/plugins/e-acsl/label.ml
+++ b/src/plugins/e-acsl/label.ml
@@ -46,11 +46,26 @@ let move (vis:Visitor.generic_frama_c_visitor) ~old new_stmt =
     new_stmt.labels <- labels @ new_stmt.labels;
     Labeled_stmts.add old new_stmt;
     (* update the gotos of the function jumping to one of the labels *)
-    let o = object
+    let o orig_stmt = object
       inherit Visitor.frama_c_inplace
-      method !vstmt_aux s = match s.skind with
-      | Goto(s_ref, _) ->
-        if Cil_datatype.Stmt.equal !s_ref old then s_ref := new_stmt;
+      (* invariant of this method: [s = Cil.memo_stmt vis#behavior orig_stmt] *)
+      method !vstmt_aux s = match s.skind, orig_stmt.skind with
+      | Goto(s_ref, loc), Goto(orig_ref, _) ->
+        if Cil_datatype.Stmt.equal !s_ref old then
+          if s_ref == orig_ref then
+            (* The memo_stmt and its origin [orig_stmt] contain a shared
+               reference because [orig_stmt] has not yet been visited by [vis]
+               (forward goto). Consequently, do not modify the ref directly but
+               replace the corresponding stmt in the memoisation table. When
+               [orig_stmt] will be visited, the visitor will automatically
+               substitute it with the updated stmt. *)
+            Cil.set_stmt vis#behavior
+              orig_stmt
+              { s with skind = Goto(ref new_stmt, loc) }
+          else
+            (* Backward goto: it has already been visited and there is no more
+               sharing. Directly update the reference. *)
+            s_ref := new_stmt;
         Cil.SkipChildren
       | _ -> Cil.DoChildren
       (* improve efficiency: skip childrens which cannot contain any label *)
@@ -60,7 +75,7 @@ let move (vis:Visitor.generic_frama_c_visitor) ~old new_stmt =
     end in
     let f = Extlib.the vis#current_func in
     let mv_labels s =
-      ignore (Visitor.visitFramacStmt o (Cil.memo_stmt vis#behavior s))
+      ignore (Visitor.visitFramacStmt (o s) (Cil.memo_stmt vis#behavior s))
     in
     List.iter mv_labels f.sallstmts
 
diff --git a/src/plugins/e-acsl/tests/runtime/goto.c b/src/plugins/e-acsl/tests/runtime/goto.c
new file mode 100644
index 0000000000000000000000000000000000000000..9369b871b5a9e886f1c485ff19ff4020009bc910
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/goto.c
@@ -0,0 +1,17 @@
+/* run.config
+   COMMENT: check a fix of a bug which occured when a [full_init] stmt is
+   COMMENT: generated for a labeled statement which a goto points to.
+   COMMENT: test both backward and forward gotos.
+*/
+
+char a;
+
+int main(void) {
+  char *b;
+  goto _LOR;
+ _LOR: b = &a;
+  if (a) goto _LOR; // dead code in order to prevent infinite loop
+                    // but still meaningfull in term of code generated by E-ACSL
+  /*@ assert \initialized(b); */
+  return 0;
+}
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_goto.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_goto.c
new file mode 100644
index 0000000000000000000000000000000000000000..7f90eb4d89b496cf3196712cc0c45062eb456ba4
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_goto.c
@@ -0,0 +1,38 @@
+/* Generated by Frama-C */
+#include "stdlib.h"
+char a;
+void __e_acsl_globals_init(void)
+{
+  __e_acsl_store_block((void *)(& a),(size_t)1);
+  __e_acsl_full_init((void *)(& a));
+  return;
+}
+
+int main(void)
+{
+  int __retres;
+  char *b;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  __e_acsl_globals_init();
+  __e_acsl_store_block((void *)(& b),(size_t)8);
+  goto _LOR;
+  _LOR: __e_acsl_full_init((void *)(& b));
+  b = & a;
+  if (a) goto _LOR;
+  /*@ assert \initialized(b); */
+  {
+    {
+      int __gen_e_acsl_initialized;
+      __gen_e_acsl_initialized = __e_acsl_initialized((void *)b,sizeof(char));
+      __e_acsl_assert(__gen_e_acsl_initialized,(char *)"Assertion",
+                      (char *)"main",(char *)"\\initialized(b)",15);
+    }
+  }
+  __retres = 0;
+  __e_acsl_delete_block((void *)(& a));
+  __e_acsl_delete_block((void *)(& b));
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/goto.err.oracle b/src/plugins/e-acsl/tests/runtime/oracle/goto.err.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/goto.res.oracle b/src/plugins/e-acsl/tests/runtime/oracle/goto.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..a0a8836bb7a329fc53da2da239850fee8b952dde
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/goto.res.oracle
@@ -0,0 +1,4 @@
+[e-acsl] beginning translation.
+FRAMAC_SHARE/libc/stdlib.h:277:[kernel] warning: No code nor implicit assigns clause for function calloc, generating default assigns from the prototype
+[e-acsl] translation done in project "e-acsl".
+FRAMAC_SHARE/e-acsl/e_acsl.h:43:[value] warning: function __e_acsl_assert: precondition got status unknown.
diff --git a/src/plugins/e-acsl/visit.ml b/src/plugins/e-acsl/visit.ml
index 2a76fd3872c10d5bf640501100b1143ed2d99cf3..dc9997ed37d194ff5427f6819e16a43de98bdcec 100644
--- a/src/plugins/e-acsl/visit.ml
+++ b/src/plugins/e-acsl/visit.ml
@@ -632,13 +632,18 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
       Printer.pp_lval checked_lv
       (not (may_safely_ignore assigned_lv))
       (Pre_analysis.must_model_lval ~kf ~stmt checked_lv);*)
-    if not (may_safely_ignore assigned_lv) && 
+    if not (may_safely_ignore assigned_lv) &&
       Mmodel_analysis.must_model_lval ~kf ~stmt checked_lv
     then
       let new_stmt =
-        Misc.mk_debug_mmodel_stmt (Misc.mk_initialize loc assigned_lv) 
+        (* must be in the new project to build a new stmt *)
+        Project.on
+          prj
+          Misc.mk_debug_mmodel_stmt
+          (Misc.mk_initialize loc assigned_lv)
       in
       let before = Cil.memo_stmt self#behavior stmt in
+      let new_stmt = Cil.memo_stmt self#behavior new_stmt in
       function_env := Env.add_stmt ~before !function_env new_stmt
 
   method !vinst = function