diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog
index 9ffefdf917e713a53bbed1c6b3f3581244ee39af..4a1e5e711d7024edf490b74237e69ea1eec76c58 100644
--- a/src/plugins/e-acsl/doc/Changelog
+++ b/src/plugins/e-acsl/doc/Changelog
@@ -21,6 +21,13 @@
 #   configure   configure
 ###############################################################################
 
+############################
+Plugin E-ACSL <next-release>
+############################
+
+-* E-ACSL       [2020-06-18] Fix support of VLA memory tracking.
+                (frama-c/e-acsl#119)
+
 #############################
 Plugin E-ACSL 21.0 (Scandium)
 #############################
diff --git a/src/plugins/e-acsl/src/code_generator/constructor.ml b/src/plugins/e-acsl/src/code_generator/constructor.ml
index 923affc32ced8756a88b0bc9bab3e60f61e07f35..9c7e60f4979d262a98e8ea79da9a41a0aa9d699d 100644
--- a/src/plugins/e-acsl/src/code_generator/constructor.ml
+++ b/src/plugins/e-acsl/src/code_generator/constructor.ml
@@ -105,12 +105,9 @@ let mk_rtl_call ~loc ?result fname args =
 (** {2 Handling the E-ACSL's C-libraries, part II} *)
 (* ************************************************************************** *)
 
-let mk_full_init_stmt ?(addr=true) vi =
+let mk_full_init_stmt vi =
   let loc = vi.vdecl in
-  let mk = mk_rtl_call ~loc "full_init" in
-  match addr, Cil.unrollType vi.vtype with
-  | _, TArray(_,Some _, _, _) | false, _ -> mk [ Cil.evar ~loc vi ]
-  | _ -> mk [ Cil.mkAddrOfVi vi ]
+  mk_rtl_call ~loc "full_init" [ Cil.evar ~loc vi ]
 
 let mk_initialize ~loc (host, offset as lv) = match host, offset with
   | Var _, NoOffset ->
@@ -150,11 +147,11 @@ let mk_store_stmt ?str_size vi =
 let mk_duplicate_store_stmt ?str_size vi =
   mk_named_store_stmt "store_block_duplicate" ?str_size vi
 
-let mk_delete_stmt vi =
+let mk_delete_stmt ?(is_addr=false) vi =
   let loc = vi.vdecl in
   let mk = mk_rtl_call ~loc "delete_block" in
-  match Cil.unrollType vi.vtype with
-  | TArray(_, Some _, _, _) -> mk [ Cil.evar ~loc vi ]
+  match is_addr, Cil.unrollType vi.vtype with
+  | _, TArray(_, Some _, _, _) | true, _ -> mk [ Cil.evar ~loc vi ]
   | _ -> mk [ Cil.mkAddrOfVi vi ]
 
 let mk_mark_readonly vi =
diff --git a/src/plugins/e-acsl/src/code_generator/constructor.mli b/src/plugins/e-acsl/src/code_generator/constructor.mli
index b286e62ca2ea8184a86152dfae56312102c76a39..c309ad478045a7e41d6582ae886931bce1b0fdcd 100644
--- a/src/plugins/e-acsl/src/code_generator/constructor.mli
+++ b/src/plugins/e-acsl/src/code_generator/constructor.mli
@@ -54,13 +54,15 @@ val mk_duplicate_store_stmt: ?str_size:exp -> varinfo -> stmt
 (** Same as [mk_store_stmt] for [__e_acsl_duplicate_store_block] that first
     checks for a previous allocation of the given varinfo. *)
 
-val mk_delete_stmt: varinfo -> stmt
+val mk_delete_stmt: ?is_addr:bool -> varinfo -> stmt
 (** Same as [mk_store_stmt] for [__e_acsl_delete_block] that observes the
-    de-allocation of the given varinfo. *)
+    de-allocation of the given varinfo.
+    If [is_addr] is false (default), take the address of varinfo. *)
 
-val mk_full_init_stmt: ?addr:bool -> varinfo -> stmt
+val mk_full_init_stmt: varinfo -> stmt
 (** Same as [mk_store_stmt] for [__e_acsl_full_init] that observes the
-    initialization of the given varinfo. *)
+    initialization of the given varinfo. The varinfo is the address to fully
+    initialize, no [addrOf] is taken. *)
 
 val mk_initialize: loc:location -> lval -> stmt
 (** Same as [mk_store_stmt] for [__e_acsl_initialize] that observes the
diff --git a/src/plugins/e-acsl/src/code_generator/global_observer.ml b/src/plugins/e-acsl/src/code_generator/global_observer.ml
index 703b4a6f6f60fca6d7f3333d31c43d3baed817b4..a89178c89937f87f01466e80690473f37d7f64e6 100644
--- a/src/plugins/e-acsl/src/code_generator/global_observer.ml
+++ b/src/plugins/e-acsl/src/code_generator/global_observer.ml
@@ -138,7 +138,7 @@ let mk_init_function () =
          let str_size = Cil.new_exp loc (SizeOfStr s) in
          Cil.mkStmtOneInstr ~valid_sid:true (Set(Cil.var vi, e, loc))
          :: Constructor.mk_store_stmt ~str_size vi
-         :: Constructor.mk_full_init_stmt ~addr:false vi
+         :: Constructor.mk_full_init_stmt vi
          :: Constructor.mk_mark_readonly vi
          :: stmts)
       stmts
diff --git a/src/plugins/e-acsl/src/code_generator/injector.ml b/src/plugins/e-acsl/src/code_generator/injector.ml
index 58f3b018d525da5cea25fead897c3ca9e1a7a35a..a0357a168fdf9772d83de8409e5734b3062a43da 100644
--- a/src/plugins/e-acsl/src/code_generator/injector.ml
+++ b/src/plugins/e-acsl/src/code_generator/injector.ml
@@ -59,17 +59,7 @@ let rec inject_in_init env kf_opt vi off = function
 let inject_in_local_init loc env kf vi = function
   | ConsInit (fvi, sz :: _, _) as init
     when Functions.Libc.is_vla_alloc_name fvi.vname ->
-    (* handle variable-length array allocation via [__fc_vla_alloc].  Here each
-       instance of [__fc_vla_alloc] is rewritten to [alloca] (that is used to
-       implement VLA) and further a custom call to [store_block] tracking VLA
-       allocation is issued. *)
-    (* KV: do not add handling [alloca] allocation here (or anywhere else for
-       that matter). Handling of [alloca] should be implemented in Frama-C
-       (eventually). This is such that each call to [alloca] becomes
-       [__fc_vla_alloc]. It is already handled using the code below. *)
-    fvi.vname <- Functions.Libc.actual_alloca;
-    (* Since we need to pass [vi] by value, cannot use [Misc.mk_store_stmt]
-       here. Do it manually. *)
+    (* add a store statement when creating a variable length array *)
     let store = Constructor.mk_store_stmt ~str_size:sz vi in
     let env = Env.add_stmt ~post:true env kf store in
     init, env
@@ -122,12 +112,6 @@ let rename_caller loc args exp = match exp.enode with
     vi.vname <- Functions.RTL.get_rtl_replacement_name vi.vname;
     exp, args
 
-  | Lval(Var vi , _) when Functions.Libc.is_vla_free_name vi.vname ->
-    (* handle variable-length array allocation via [__fc_vla_free]. Rewrite its
-       name to [delete_block]. The rest is in place. *)
-    vi.vname <- Functions.RTL.mk_api_name "delete_block";
-    exp, args
-
   | Lval(Var vi, _)
     when Options.Validate_format_strings.get ()
       && Functions.Libc.is_printf_name vi.vname
@@ -200,6 +184,17 @@ let inject_in_instr env kf stmt = function
       | _ ->
         env
     in
+    (* if this is a call to free a vla, add a call to delete_block *)
+    let env =
+      if Functions.Libc.is_vla_free caller then
+        match args with
+        | [ { enode = CastE (_, { enode = Lval (Var vi, NoOffset) }) } ] ->
+          let delete_block = Constructor.mk_delete_stmt ~is_addr:true vi in
+          Env.add_stmt env kf delete_block
+        | _ -> Options.fatal "The normalization of __fc_vla_free() has changed"
+      else
+        env
+    in
     Call(result, caller, args, loc), env
 
   | Local_init(vi, linit, loc) ->
diff --git a/src/plugins/e-acsl/src/main.ml b/src/plugins/e-acsl/src/main.ml
index a7f26523d4c08bd8b4028b8522d8f3073ecb857c..0c6c931c4754a04db314b86e69710985c304155f 100644
--- a/src/plugins/e-acsl/src/main.ml
+++ b/src/plugins/e-acsl/src/main.ml
@@ -205,13 +205,43 @@ let change_printer =
       let module Printer_class(X: Printer.PrinterClass) = struct
         class printer = object
           inherit X.printer as super
+
           method !varinfo fmt vi =
-            if vi.Cil_types.vghost || vi.Cil_types.vstorage <> Cil_types.Extern
-            then
-              super#varinfo fmt vi
-            else
+            if Functions.Libc.is_vla_alloc_name vi.Cil_types.vname then
+              (* Replace VLA allocation with calls to [__builtin_alloca] *)
+              Format.fprintf fmt "%s" Functions.Libc.actual_alloca
+            else if (not vi.vghost) && vi.vstorage == Cil_types.Extern then
+              (* Replace calls to Frama-C builtins with calls to their original
+                 version from the libc *)
               let s = Str.replace_first r "" vi.Cil_types.vname in
               Format.fprintf fmt "%s" s
+            else
+              (* Otherwise use the original printer *)
+              super#varinfo fmt vi
+
+          method !instr fmt i =
+            match i with
+            | Call(_, fct, _, _) when Functions.Libc.is_vla_free fct ->
+              (* Nothing to print: VLA deallocation is done automatically when
+                 leaving the scope *)
+              Format.fprintf fmt "/* ";
+              super#instr fmt i;
+              Format.fprintf fmt " */"
+            | _ ->
+              super#instr fmt i
+
+          method !global fmt g =
+            let is_vla_builtin vi =
+              Functions.Libc.is_vla_alloc_name vi.Cil_types.vname ||
+              Functions.Libc.is_vla_free_name vi.Cil_types.vname
+            in
+            match g with
+            | GFunDecl (_, vi, _) when is_vla_builtin vi ->
+              (* Nothing to print: the VLA builtins don't have an original libc
+                 version. *)
+              ()
+            | _ ->
+              super#global fmt g
         end
       end in
       Printer.update_printer (module Printer_class: Printer.PrinterExtension)
diff --git a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vla.c b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vla.c
index 646d3b855887d7fdf258439c0fb0ee5483127a1f..d2039f2b5ee5f5dc7add5b7346d91dfabeb5e52a 100644
--- a/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vla.c
+++ b/src/plugins/e-acsl/tests/memory/oracle_ci/gen_vla.c
@@ -2,12 +2,6 @@
 #include "stdio.h"
 #include "stdlib.h"
 int LEN = 10;
-/*@ assigns \nothing;
-    frees p; */
- __attribute__((__FC_BUILTIN__)) void __e_acsl_delete_block(void *p);
-
-/* compiler builtin: 
-    __attribute__((__FC_BUILTIN__)) void *__builtin_alloca(unsigned long size);   */
 int main(int argc, char **argv)
 {
   int __retres;
@@ -67,6 +61,7 @@ int main(int argc, char **argv)
   }
   __retres = 0;
   __e_acsl_delete_block((void *)arr);
+  /* __fc_vla_free((void *)arr); */
   __e_acsl_delete_block((void *)(& arr));
   __e_acsl_memory_clean();
   return __retres;