diff --git a/src/plugins/e-acsl/misc.ml b/src/plugins/e-acsl/misc.ml
index a1e78558beae129f7a85f2585ae7f97bfeb01764..2616dfe348ecf0cccffe24ea501655179a83052c 100644
--- a/src/plugins/e-acsl/misc.ml
+++ b/src/plugins/e-acsl/misc.ml
@@ -143,9 +143,6 @@ let get_orig_name kf =
   let name = Kernel_function.get_name kf in
   strip_prefix e_acsl_gen_prefix name
 
-let is_alloc_name fn =
-  fn = "malloc" || fn = "free" || fn = "realloc" || fn = "calloc"
-
 let mk_api_name fname =
   e_acsl_api_prefix ^ fname
 
diff --git a/src/plugins/e-acsl/misc.mli b/src/plugins/e-acsl/misc.mli
index 10a2a111be7c8d3101a0eb0db7705ca7a8fde82d..25aae974b69f88db507a7f3bff88e48eb9e8bdfa 100644
--- a/src/plugins/e-acsl/misc.mli
+++ b/src/plugins/e-acsl/misc.mli
@@ -101,10 +101,6 @@ pointer and integer parts. *)
 (** {2 Handling prefixes of generated library functions and variables} *)
 (* ************************************************************************** *)
 
-val is_alloc_name: string -> bool
-(** @return true if a given string matches the name of a
-   memory-allocation function recognized by E-ACSL. *)
-
 val mk_api_name: string -> string
 (** @return given some base name append it with a prefix used
     by functions and variables in the public API of E-ACSL runtime library.
diff --git a/src/plugins/e-acsl/mmodel_analysis.ml b/src/plugins/e-acsl/mmodel_analysis.ml
index 5ef4a927fdb6bdae42cb6902c235c14f22e052be..9e7c308a9af4b092b6a49dc97cc98afdb27b692f 100644
--- a/src/plugins/e-acsl/mmodel_analysis.ml
+++ b/src/plugins/e-acsl/mmodel_analysis.ml
@@ -31,15 +31,15 @@ open Cil_datatype
 let dkey = Options.dkey_analysis
 module Env: sig
   val has_heap_allocations: unit -> bool
-  val check_heap_allocations: string -> unit
+  val check_heap_allocations: kernel_function -> unit
   val default_varinfos: Varinfo.Hptset.t option -> Varinfo.Hptset.t
   val apply: (kernel_function -> 'a) -> kernel_function -> 'a
   val clear: unit -> unit
   val add: kernel_function -> Varinfo.Hptset.t option Stmt.Hashtbl.t -> unit
   val add_init: kernel_function -> Varinfo.Hptset.t option -> unit
   val mem_init: kernel_function -> Varinfo.Hptset.t option -> bool
-  val find: kernel_function -> Varinfo.Hptset.t option Stmt.Hashtbl.t 
-  module StartData: 
+  val find: kernel_function -> Varinfo.Hptset.t option Stmt.Hashtbl.t
+  module StartData:
     Dataflow.StmtStartData with type data = Varinfo.Hptset.t option
   val is_consolidated: unit -> bool
   val consolidate: Varinfo.Hptset.t -> unit
@@ -49,11 +49,13 @@ end = struct
 
   let heap_allocation_ref = ref false
   let has_heap_allocations () = !heap_allocation_ref
-  let check_heap_allocations fn =
-    heap_allocation_ref := !heap_allocation_ref || Misc.is_alloc_name fn
+  let check_heap_allocations kf =
+    (* a function with no definition potentially allocates memory *)
+    heap_allocation_ref :=
+      !heap_allocation_ref || not (Kernel_function.is_definition kf)
 
   let current_kf = ref None
-  let default_varinfos = function None -> Varinfo.Hptset.empty | Some s -> s 
+  let default_varinfos = function None -> Varinfo.Hptset.empty | Some s -> s
 
   let apply f kf =
     let old = !current_kf in
@@ -69,7 +71,7 @@ end = struct
   module S = Set.Make(Datatype.Option(Varinfo.Hptset))
 
   let tbl_init = Kernel_function.Hashtbl.create 7
-  let add_init kf init = 
+  let add_init kf init =
     let set =
       try Kernel_function.Hashtbl.find tbl_init kf
       with Not_found -> S.empty
@@ -77,21 +79,21 @@ end = struct
     let set = S.add init set in
     Kernel_function.Hashtbl.replace tbl_init kf set
 
-  let mem_init kf init = 
-    try 
+  let mem_init kf init =
+    try
       let set = Kernel_function.Hashtbl.find tbl_init kf in
       S.mem init set
-    with Not_found -> 
+    with Not_found ->
       false
 
   module StartData = struct
     type data = Varinfo.Hptset.t option
-    let apply f = 
+    let apply f =
       try
         let kf = Extlib.opt_conv (Kernel_function.dummy()) !current_kf in
         let h = Kernel_function.Hashtbl.find tbl kf in
         f h
-      with Not_found -> 
+      with Not_found ->
         assert false
     let clear () = apply Stmt.Hashtbl.clear
     let mem k = apply Stmt.Hashtbl.mem k
@@ -108,11 +110,11 @@ end = struct
   let consolidated_set = ref Varinfo.Hptset.empty
   let is_consolidated_ref = ref false
 
-  let consolidate set = 
+  let consolidate set =
     let set = Varinfo.Hptset.union set !consolidated_set in
     consolidated_set := set
 
-  let consolidated_mem v = 
+  let consolidated_mem v =
     is_consolidated_ref := true;
     Varinfo.Hptset.mem v !consolidated_set
 
@@ -121,7 +123,7 @@ end = struct
   let is_empty () =
     try
       Kernel_function.Hashtbl.iter
-        (fun _ h -> 
+        (fun _ h ->
           Stmt.Hashtbl.iter
             (fun _ set -> match set with
             | None -> ()
@@ -132,7 +134,7 @@ end = struct
     with Exit ->
       false
 
-  let clear () = 
+  let clear () =
     Kernel_function.Hashtbl.clear tbl;
     consolidated_set := Varinfo.Hptset.empty;
     is_consolidated_ref := false;
@@ -140,7 +142,7 @@ end = struct
 
 end
 
-let reset () = 
+let reset () =
   Options.feedback ~dkey ~level:2 "clearing environment.";
   Env.clear ()
 
@@ -172,17 +174,17 @@ module rec Transfer
   let combineStmtStartData stmt ~old state = match stmt.skind, old, state with
     | _, _, None -> assert false
     | _, None, Some _ -> Some state (* [old] already included in [state] *)
-    | Return _, Some old, Some new_ -> 
+    | Return _, Some old, Some new_ ->
       Some (Some (Varinfo.Hptset.union old new_))
-    | _, Some old, Some new_ -> 
+    | _, Some old, Some new_ ->
       if Varinfo.Hptset.equal old new_ then
         None
       else
         Some (Some (Varinfo.Hptset.union old new_))
 
   (** Take the data from two successors and combine it *)
-  let combineSuccessors s1 s2 = 
-    Some 
+  let combineSuccessors s1 s2 =
+    Some
       (Varinfo.Hptset.union (Env.default_varinfos s1) (Env.default_varinfos s2))
 
   let is_ptr_or_array ty = Cil.isPointerType ty || Cil.isArrayType ty
@@ -192,43 +194,43 @@ module rec Transfer
     is_ptr_or_array ty
 
   let rec base_addr_node = function
-    | Lval lv | AddrOf lv | StartOf lv -> 
+    | Lval lv | AddrOf lv | StartOf lv ->
       (match lv with
       | Var vi, _ -> Some vi
       | Mem e, _ -> base_addr e)
-    | BinOp((PlusPI | IndexPI | MinusPI), e1, e2, _) -> 
+    | BinOp((PlusPI | IndexPI | MinusPI), e1, e2, _) ->
       if is_ptr_or_array_exp e1 then base_addr e1
       else begin
         assert (is_ptr_or_array_exp e2);
         base_addr e2
       end
     | Info(e, _) | CastE(_, e) -> base_addr e
-    | BinOp((MinusPP | PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt 
+    | BinOp((MinusPP | PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt
                 | Lt | Gt | Le | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr),
             _, _, _)
-    | UnOp _ | Const _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ 
-    | AlignOfE _ -> 
+    | UnOp _ | Const _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _
+    | AlignOfE _ ->
       None
 
   and base_addr e = base_addr_node e.enode
 
   let extend_to_expr always state lhost e =
     let add_vi state vi =
-      if is_ptr_or_array_exp e && (always || Varinfo.Hptset.mem vi state) then 
+      if is_ptr_or_array_exp e && (always || Varinfo.Hptset.mem vi state) then
         match base_addr e with
         | None -> state
-        | Some vi_e -> 
+        | Some vi_e ->
           Options.feedback ~level:4 ~dkey
             "monitoring %a from %a."
             Printer.pp_varinfo vi_e
             Printer.pp_lval (lhost, NoOffset);
           Varinfo.Hptset.add vi_e state
-      else 
+      else
         state
     in
     match lhost with
     | Var vi -> add_vi state vi
-    | Mem e -> 
+    | Mem e ->
       match base_addr e with
       | None -> state
       | Some vi -> add_vi state vi
@@ -241,10 +243,10 @@ module rec Transfer
         true
       else
         state, false
-    | AddrOf(lhost, _) -> 
+    | AddrOf(lhost, _) ->
       extend_to_expr true state lhost (Cil.new_exp ~loc:e.eloc (Lval lv)),
       true
-    | BinOp((PlusPI | IndexPI | MinusPI), e1, e2, _) -> 
+    | BinOp((PlusPI | IndexPI | MinusPI), e1, e2, _) ->
       if is_ptr_or_array_exp e1 then extend_from_addr state lv e1
       else begin
         assert (is_ptr_or_array_exp e2);
@@ -258,10 +260,10 @@ module rec Transfer
     let state, always = extend_from_addr state lv e in
     extend_to_expr always state lhost e
 
-  let rec register_term_lval kf varinfos (thost, _) = 
+  let rec register_term_lval kf varinfos (thost, _) =
     let add_vi kf vi =
-      Options.feedback ~level:4 ~dkey "monitoring %a from annotation of %a." 
-        Printer.pp_varinfo vi 
+      Options.feedback ~level:4 ~dkey "monitoring %a from annotation of %a."
+        Printer.pp_varinfo vi
         Kernel_function.pretty kf;
       Varinfo.Hptset.add vi varinfos
     in
@@ -272,7 +274,7 @@ module rec Transfer
     | TMem t -> register_term kf varinfos t
 
   and register_term kf varinfos term = match term.term_node with
-    | TLval tlv | TAddrOf tlv | TStartOf tlv -> 
+    | TLval tlv | TAddrOf tlv | TStartOf tlv ->
       register_term_lval kf varinfos tlv
     | TCastE(_, t) | Tat(t, _) | Tlet(_, t) ->
       register_term kf varinfos t
@@ -282,7 +284,7 @@ module rec Transfer
     | TBinOp((PlusPI | IndexPI | MinusPI), t1, t2) ->
       (match t1.term_type with
       | Ctype ty when is_ptr_or_array ty -> register_term kf varinfos t1
-      | _ -> 
+      | _ ->
         match t2.term_type with
         | Ctype ty when is_ptr_or_array ty -> register_term kf varinfos t2
         | _ -> assert false)
@@ -319,22 +321,22 @@ module rec Transfer
     | Pseparated _ -> Error.not_yet "\\separated"
     | Pdangling _ -> Error.not_yet "\\dangling"
     | Ptrue | Pfalse | Papp _ | Prel _
-    | Pand _ | Por _ | Pxor _ | Pimplies _ | Piff _ | Pnot _ | Pif _ 
+    | Pand _ | Por _ | Pxor _ | Pimplies _ | Piff _ | Pnot _ | Pif _
     | Plet _ | Pforall _ | Pexists _ | Pat _ | Psubtype _ ->
       Cil.DoChildren
     method !vterm term = match term.term_node with
     | Tbase_addr(_, t) | Toffset(_, t) | Tblock_length(_, t) ->
       state_ref := register_term kf !state_ref t;
       Cil.DoChildren
-    | TConst _ | TSizeOf _ | TSizeOfStr _ | TAlignOf _  | Tnull | Ttype _ 
-    | Tempty_set -> 
+    | TConst _ | TSizeOf _ | TSizeOfStr _ | TAlignOf _  | Tnull | Ttype _
+    | Tempty_set ->
       (* no left-value inside inside: skip for efficiency *)
       Cil.SkipChildren
     | TUnOp _ | TBinOp _ | Ttypeof _ | TSizeOfE _
     | TLval _ | TAlignOfE _ | TCastE _ | TAddrOf _
     | TStartOf _ | Tapp _ | Tlambda _ | TDataCons _ | Tif _ | Tat _
     | TCoerce _ | TCoerceE _ | TUpdate _ | Tunion _ | Tinter _
-    | Tcomprehension _ | Trange _ | Tlet _ | TLogic_coerce _ -> 
+    | Tcomprehension _ | Trange _ | Tlet _ | TLogic_coerce _ ->
       (* potential sub-term inside *)
       Cil.DoChildren
     method !vlogic_label _ = Cil.SkipChildren
@@ -343,11 +345,11 @@ module rec Transfer
       (* potential RTE *)
       state_ref := register_term kf !state_ref t;
       Cil.DoChildren
-    | TVar _ | TResult _ -> 
+    | TVar _ | TResult _ ->
       Cil.SkipChildren
   end
 
-let register_predicate kf pred state = 
+let register_predicate kf pred state =
   let state_ref = ref state in
   Error.handle
     (fun () ->
@@ -356,11 +358,11 @@ let register_predicate kf pred state =
     ();
   !state_ref
 
-  let register_code_annot kf a state = 
+  let register_code_annot kf a state =
     let state_ref = ref state in
     Error.handle
       (fun () ->
-        ignore 
+        ignore
           (Visitor.visitFramacCodeAnnotation (register_object kf state_ref) a))
       ();
     !state_ref
@@ -371,7 +373,7 @@ let register_predicate kf pred state =
         List.fold_left (fun state (_, init) -> do_init vi init state) state l
 
   let register_initializers state =
-    let do_one vi init state = match init.init with 
+    let do_one vi init state = match init.init with
       | None -> state
       | Some init -> do_init vi init state
     in
@@ -387,37 +389,37 @@ let register_predicate kf pred state =
   let doStmt stmt =
     let _, kf = Kernel_function.find_from_sid stmt.sid in
     let is_first =
-      try Stmt.equal stmt (Kernel_function.find_first_stmt kf) 
+      try Stmt.equal stmt (Kernel_function.find_first_stmt kf)
       with Kernel_function.No_Statement -> assert false
     in
     let is_last =
-      try Stmt.equal stmt (Kernel_function.find_return kf) 
+      try Stmt.equal stmt (Kernel_function.find_return kf)
       with Kernel_function.No_Statement -> assert false
     in
-    Dataflow.Post 
+    Dataflow.Post
       (fun state ->
         let state = Env.default_varinfos state in
-        let state = 
-          if (is_first || is_last) && Misc.is_generated_kf kf then 
+        let state =
+          if (is_first || is_last) && Misc.is_generated_kf kf then
             Annotations.fold_behaviors
-              (fun _ bhv s -> 
+              (fun _ bhv s ->
                 let handle_annot test f s =
-                  if test then 
+                  if test then
                     f (fun _ p s -> register_predicate kf p s) kf bhv.b_name s
                   else
                     s
                 in
                 let s = handle_annot is_first Annotations.fold_requires s in
                 let s = handle_annot is_first Annotations.fold_assumes s in
-                handle_annot 
-                  is_last 
+                handle_annot
+                  is_last
                   (fun f -> Annotations.fold_ensures (fun e (_, p) -> f e p)) s)
               kf
               state
           else
             state
         in
-        let state = 
+        let state =
           Annotations.fold_code_annot
             (fun _ -> register_code_annot kf) stmt state
         in
@@ -426,14 +428,14 @@ let register_predicate kf pred state =
             let rtes = Rte.stmt kf stmt in
             List.fold_left
               (fun state a -> register_code_annot kf a state) state rtes
-          else 
+          else
             state
         in
         let state =
         (* take initializers into account *)
           if is_first then
             let main, lib = Globals.entry_point () in
-            if Kernel_function.equal kf main && not lib then 
+            if Kernel_function.equal kf main && not lib then
               register_initializers state
             else
               state
@@ -443,82 +445,82 @@ let register_predicate kf pred state =
         Some state)
 
   let do_call res f args state =
-    Env.check_heap_allocations f.vname;
     let kf = Globals.Functions.get f in
-        let params = Globals.Functions.get_params kf in
-        let state =
-          if Kernel_function.is_definition kf then
-            try
-      (* compute the initial state of the called function *)
-              let init =
-                List.fold_left2
-                  (fun acc p a -> match base_addr a with
-                  | None -> acc
-                 | Some vi ->
-                   if Varinfo.Hptset.mem vi state
-                    then Varinfo.Hptset.add p acc
-                    else acc)
-                  state
-                  params
+    Env.check_heap_allocations kf;
+    let params = Globals.Functions.get_params kf in
+    let state =
+      if Kernel_function.is_definition kf then
+        try
+          (* compute the initial state of the called function *)
+          let init =
+            List.fold_left2
+              (fun acc p a -> match base_addr a with
+              | None -> acc
+              | Some vi ->
+                if Varinfo.Hptset.mem vi state
+                then Varinfo.Hptset.add p acc
+                else acc)
+              state
+              params
               args
-              in
+          in
           let init = match res with
-                | None -> init
-                | Some lv ->
-                  match base_addr_node (Lval lv) with
-                  | None -> init
-                  | Some vi ->
+            | None -> init
+            | Some lv ->
+              match base_addr_node (Lval lv) with
+              | None -> init
+              | Some vi ->
                 if Varinfo.Hptset.mem vi state
-                    then Varinfo.Hptset.add (Misc.result_vi kf) init
-                    else init
-              in
-              let state = Compute.get ~init kf in
-      (* compute the resulting state by keeping arguments whenever the
-         corresponding formals must be kept *)
-              List.fold_left2
-                (fun acc p a -> match base_addr a with
-                | None -> acc
-                | Some vi ->
-                 if Varinfo.Hptset.mem p state then Varinfo.Hptset.add vi acc
-                  else acc)
-                state
-                params
+                then Varinfo.Hptset.add (Misc.result_vi kf) init
+                else init
+          in
+          let state = Compute.get ~init kf in
+          (* compute the resulting state by keeping arguments whenever the
+             corresponding formals must be kept *)
+          List.fold_left2
+            (fun acc p a -> match base_addr a with
+            | None -> acc
+            | Some vi ->
+              if Varinfo.Hptset.mem p state then Varinfo.Hptset.add vi acc
+              else acc)
+            state
+            params
             args
         with Invalid_argument _ ->
-              Options.warning ~current:true
+          Options.warning ~current:true
             "ignoring effect of variadic function %a"
-                Kernel_function.pretty
-                kf;
-              state
-          else
-            state
-        in
+            Kernel_function.pretty
+            kf;
+          state
+      else
+        state
+    in
     let state = match res, Kernel_function.is_definition kf with
-          | None, _ | _, false -> state
-          | Some (lhost, _), true ->
-    (* add the result if \result must be kept after calling the kf *)
-            let vi = Misc.result_vi kf in
+      | None, _ | _, false -> state
+      | Some (lhost, _), true ->
+        (* add the result if \result must be kept after calling the kf *)
+        let vi = Misc.result_vi kf in
         if  Varinfo.Hptset.mem vi state then
-              match lhost with
-              | Var vi -> Varinfo.Hptset.add vi state
+          match lhost with
+          | Var vi -> Varinfo.Hptset.add vi state
           | Mem e ->
-                match base_addr e with
-                | None -> state
-                | Some vi -> Varinfo.Hptset.add vi state
-            else
-              state
-        in
-        Dataflow.Done (Some state)
+            match base_addr e with
+            | None -> state
+            | Some vi -> Varinfo.Hptset.add vi state
+        else
+          state
+    in
+    Dataflow.Done (Some state)
 
 
   (** The (backwards) transfer function for an instruction. The
       [(Cil.CurrentLoc.get ())] is set before calling this. If it returns
       None, then we have some default handling. Otherwise, the returned data is
       the data before the branch (not considering the exception handlers) *)
-  let doInstr _stmt instr state = 
+  let doInstr _stmt instr state =
     let state = Env.default_varinfos state in
     match instr with
-    | Set(lv, e, _) -> 
+    | Set(lv, e, _) ->
       let state = handle_assignment state lv e in
       Dataflow.Done (Some state)
     | Local_init(v,AssignInit i,_) ->
@@ -535,13 +537,13 @@ let register_predicate kf pred state =
         Options.warning ~current:true
           "function pointers may introduce too limited instrumentation.";
 (* imprecise function call: keep each argument *)
-        Dataflow.Done 
+        Dataflow.Done
           (Some
              (List.fold_left
                 (fun acc e -> match base_addr e with
                 | None -> acc
                 | Some vi -> Varinfo.Hptset.add vi acc)
-                state 
+                state
                 l)))
     | Asm _ -> Error.not_yet "asm"
     | Skip _ | Code_annot _ -> Dataflow.Default
@@ -556,20 +558,20 @@ let register_predicate kf pred state =
       Stmts_graph.stmt_can_reach kf], where [kf] is the kernel_function
       being analyzed; [let stmt_can_reach _ _ = true] is also correct,
       albeit less efficient *)
-  let stmt_can_reach stmt = 
+  let stmt_can_reach stmt =
     let _, kf = Kernel_function.find_from_sid stmt.sid in
     Stmts_graph.stmt_can_reach kf stmt
 
 end
 
-and Compute: sig 
-  val get: ?init:Varinfo.Hptset.t -> kernel_function -> Varinfo.Hptset.t 
+and Compute: sig
+  val get: ?init:Varinfo.Hptset.t -> kernel_function -> Varinfo.Hptset.t
 end = struct
 
   module D = Dataflow.Backwards(Transfer)
 
-  let compute init_set kf = 
-    Options.feedback ~dkey ~level:2 "entering in function %a." 
+  let compute init_set kf =
+    Options.feedback ~dkey ~level:2 "entering in function %a."
       Kernel_function.pretty kf;
     assert (not (Misc.is_library_loc (Kernel_function.get_location kf)));
     let tbl, is_init =
@@ -581,16 +583,16 @@ end = struct
     (try
        let fundec = Kernel_function.get_definition kf in
        let stmts, returns = Dataflow.find_stmts fundec in
-       if is_init then 
+       if is_init then
          Extlib.may
-           (fun set -> 
-             List.iter 
-               (fun s -> 
-                 let old = 
-                   try Extlib.the (Stmt.Hashtbl.find tbl s) 
+           (fun set ->
+             List.iter
+               (fun s ->
+                 let old =
+                   try Extlib.the (Stmt.Hashtbl.find tbl s)
                    with Not_found -> assert false
                  in
-                 Stmt.Hashtbl.replace 
+                 Stmt.Hashtbl.replace
                    tbl
                    s
                    (Some (Varinfo.Hptset.union set old)))
@@ -599,14 +601,14 @@ end = struct
        else begin
          List.iter (fun s -> Stmt.Hashtbl.add tbl s None) stmts;
          Extlib.may
-           (fun set -> 
+           (fun set ->
              List.iter (fun s -> Stmt.Hashtbl.replace tbl s (Some set)) returns)
            init_set
        end;
        D.compute stmts
-     with Kernel_function.No_Definition | Kernel_function.No_Statement -> 
+     with Kernel_function.No_Definition | Kernel_function.No_Statement ->
        ());
-    Options.feedback ~dkey ~level:2 "function %a done." 
+    Options.feedback ~dkey ~level:2 "function %a done."
       Kernel_function.pretty kf;
     tbl
 
@@ -617,22 +619,22 @@ end = struct
       try
         let stmt = Kernel_function.find_first_stmt kf in
 (*      Options.feedback "GETTING %a" Kernel_function.pretty kf;*)
-        let tbl = 
+        let tbl =
           if Env.mem_init kf init then
             try Env.find kf with Not_found -> assert false
           else begin
     (* WARN: potentially incorrect in case of recursive call *)
             Env.add_init kf init;
-            Env.apply (compute init) kf 
+            Env.apply (compute init) kf
           end
         in
         try
           let set = Stmt.Hashtbl.find tbl stmt in
           Env.default_varinfos set
         with Not_found ->
-          Options.fatal "[pre_analysis] stmt never analyzed: %a" 
+          Options.fatal "[pre_analysis] stmt never analyzed: %a"
             Printer.pp_stmt stmt
-      with Kernel_function.No_Statement -> 
+      with Kernel_function.No_Statement ->
         Varinfo.Hptset.empty
 
 end
@@ -671,17 +673,17 @@ let must_model_vi ?kf ?stmt vi =
   | Some _, None ->
     assert false
   | Some stmt, Some kf  ->
-    if not (Env.is_consolidated ()) then 
+    if not (Env.is_consolidated ()) then
       ignore (consolidated_must_model_vi vi);
     try
       let tbl = Env.find kf in
       try
 let set = Stmt.Hashtbl.find tbl stmt in
 Varinfo.Hptset.mem vi (Env.default_varinfos set)
-      with Not_found -> 
+      with Not_found ->
 (* new statement *)
 consolidated_must_model_vi vi
-    with Not_found -> 
+    with Not_found ->
       (* [kf] is dead code *)
       false
  *)
@@ -692,15 +694,15 @@ let rec must_model_lval ?kf ?stmt = function
 and must_model_exp ?kf ?stmt e = match e.enode with
   | Lval lv | AddrOf lv | StartOf lv -> must_model_lval ?kf ?stmt lv
   | BinOp((PlusPI | IndexPI | MinusPI), e1, _, _) -> must_model_exp ?kf ?stmt e1
-  | BinOp(MinusPP, e1, e2, _) -> 
+  | BinOp(MinusPP, e1, e2, _) ->
     must_model_exp ?kf ?stmt e1 || must_model_exp ?kf ?stmt e2
   | Info(e, _) | CastE(_, e) -> must_model_exp ?kf ?stmt e
-  | BinOp((PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt 
+  | BinOp((PlusA | MinusA | Mult | Div | Mod |Shiftlt | Shiftrt
               | Lt | Gt | Le | Ge | Eq | Ne | BAnd | BXor | BOr | LAnd | LOr),
           _, _, _)
   | Const _ -> (* possible in case of static address *) false
-  | UnOp _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ 
-  | AlignOfE _ -> 
+  | UnOp _ | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _
+  | AlignOfE _ ->
     Options.fatal "[pre_analysis] unexpected expression %a" Exp.pretty e
 
 let must_model_vi ?kf ?stmt vi =
@@ -709,7 +711,7 @@ let must_model_vi ?kf ?stmt vi =
     (Options.Full_mmodel.get ()
      || Error.generic_handle (must_model_vi ?kf ?stmt) false vi)
 
-let must_model_lval ?kf ?stmt lv = 
+let must_model_lval ?kf ?stmt lv =
   Options.Full_mmodel.get ()
   || Error.generic_handle (must_model_lval ?kf ?stmt) false lv
 
diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
index 5c42f259ca2aeaebdb89e8e95f11408b8254a9d1..daeefeb20f4eccda8f32f813078993ed0f36feff 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
@@ -223,11 +223,14 @@ static const uint64_t static_readonly_masks [] = {
   DVASSERT(((uintptr_t)_addr) % HEAP_SEGMENT == 0,  \
       "Heap base address %a is unaligned", _addr)
 
+#define DVALIDATE_MEMORY_INIT \
+  DVASSERT(mem_layout.initialized != 0, "Un-initialized shadow layout", NULL)
+
 /* Debug function making sure that the order of program segments is as expected
  * and that the program and the shadow segments used do not overlap. */
 static void validate_memory_layout() {
   /* Check that the struct holding memory layout is marked as initialized. */
-  DVASSERT(mem_layout.initialized != 0, "Un-initialized shadow layout", NULL);
+  DVALIDATE_MEMORY_INIT;
   /* Make sure the order of program segments is as expected, i.e.,
    * top to bottom: stack -> tls -> heap -> global */
 
@@ -375,6 +378,7 @@ static void validate_memory_layout() {
 
 #else
 /*! \cond exclude from doxygen */
+#  define DVALIDATE_MEMORY_INIT
 #  define DVALIDATE_SHADOW_LAYOUT
 #  define DVALIDATE_HEAP_ACCESS
 #  define DVALIDATE_STATIC_ACCESS
@@ -769,7 +773,9 @@ static size_t heap_allocation_size = 0;
  * correspond to `unusable space`.
  * \b WARNING: Current implementation assumes that the size of a heap segment
  * does not exceed 64 bytes. */
-static void set_heap_segment(void *ptr, size_t size, size_t alloc_size, size_t init) {
+static void set_heap_segment(void *ptr, size_t size, size_t alloc_size,
+    size_t init, const char *function) {
+  DVALIDATE_MEMORY_INIT;
   /* Ensure the shadowed block in on the tracked heap portion */
   DVALIDATE_IS_ON_HEAP(((uintptr_t)ptr) - HEAP_SEGMENT, size);
   DVALIDATE_ALIGNMENT(ptr); /* Make sure alignment is right */
@@ -820,7 +826,7 @@ static void* shadow_malloc(size_t size) {
     (char*)native_aligned_alloc(HEAP_SEGMENT, alloc_size) : NULL;
 
   if (res)
-    set_heap_segment(res, size, alloc_size, 0);
+    set_heap_segment(res, size, alloc_size, 0, "malloc");
 
   return res;
 }
@@ -841,7 +847,7 @@ static void* shadow_calloc(size_t nmemb, size_t size) {
 
   if (res) {
     memset(res, 0, size);
-    set_heap_segment(res, size, alloc_size, 1);
+    set_heap_segment(res, size, alloc_size, 1, "calloc");
   }
 
   return res;
@@ -856,7 +862,8 @@ static void* shadow_calloc(size_t nmemb, size_t size) {
  *
  * NOTE: ::unset_heap_segment assumes that `ptr` is a base address of an
  * allocated heap memory block, i.e., `freeable(ptr)` evaluates to true. */
-static void unset_heap_segment(void *ptr, int init) {
+static void unset_heap_segment(void *ptr, int init, const char *function) {
+  DVALIDATE_MEMORY_INIT;
   DVALIDATE_FREEABLE(((uintptr_t)ptr));
   /* Base address of shadow block */
   uintptr_t *base_shadow = (uintptr_t*)HEAP_SHADOW(ptr);
@@ -878,7 +885,7 @@ static void unset_heap_segment(void *ptr, int init) {
 static void shadow_free(void *ptr) {
   if (ptr != NULL) { /* NULL is a valid behaviour */
     if (freeable(ptr)) {
-      unset_heap_segment(ptr, 1);
+      unset_heap_segment(ptr, 1, "free");
       native_free(ptr);
     } else {
       vabort("Not a start of block (%a) in free\n", ptr);
@@ -910,10 +917,10 @@ static void* shadow_realloc(void *ptr, size_t size) {
         size_t old_alloc_size = ALLOC_SIZE(old_size);
 
         /* Nullify old representation */
-        unset_heap_segment(ptr, 0);
+        unset_heap_segment(ptr, 0, "realloc");
 
         /* Set up new block shadow */
-        set_heap_segment(res, size, alloc_size, 0);
+        set_heap_segment(res, size, alloc_size, 0, "realloc");
 
         /* Move init shadow */
         unsigned char* old_init_shadow  = (unsigned char*)HEAP_INIT_SHADOW(ptr);
@@ -959,7 +966,7 @@ static void *shadow_aligned_alloc(size_t alignment, size_t size) {
 
   char *res = native_aligned_alloc(alignment, size);
   if (res)
-    set_heap_segment(res, size, ALLOC_SIZE(size), 0);
+    set_heap_segment(res, size, ALLOC_SIZE(size), 0, "aligned_alloc");
 
   return (void*)res;
 }
@@ -980,7 +987,7 @@ static int shadow_posix_memalign(void **memptr, size_t alignment, size_t size) {
 
   int res = native_posix_memalign(memptr, alignment, size);
   if (!res) {
-    set_heap_segment(*memptr, size, ALLOC_SIZE(size), 0);
+    set_heap_segment(*memptr, size, ALLOC_SIZE(size), 0, "posix_memalign");
   }
   return res;
 }
diff --git a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1398.c b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1398.c
index 2e7d6aa1674c2c8b302a45b86a119bd8eb24085b..435d9f52ff4a1f29b9acc6872f535a40264c7bd4 100644
--- a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1398.c
+++ b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1398.c
@@ -1,16 +1,30 @@
 /* Generated by Frama-C */
 #include "stdio.h"
 #include "stdlib.h"
+char *__gen_e_acsl_literal_string;
+void __e_acsl_globals_init(void)
+{
+  __gen_e_acsl_literal_string = "X=%d, t[0]=%d, t[1]=%d\n";
+  __e_acsl_store_block((void *)__gen_e_acsl_literal_string,
+                       sizeof("X=%d, t[0]=%d, t[1]=%d\n"));
+  __e_acsl_full_init((void *)__gen_e_acsl_literal_string);
+  __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string);
+  return;
+}
+
 int main(void)
 {
   int __retres;
   int t[2];
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  __e_acsl_globals_init();
   int x = 0;
   int i = 1;
   t[0] = 1;
   t[1] = 2;
-  printf("X=%d, t[0]=%d, t[1]=%d\n",x,t[0],t[i]);
+  printf(__gen_e_acsl_literal_string,x,t[0],t[i]);
   __retres = 0;
+  __e_acsl_memory_clean();
   return __retres;
 }
 
diff --git a/src/plugins/e-acsl/tests/runtime/hidden_malloc.c b/src/plugins/e-acsl/tests/runtime/hidden_malloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..a33c036ea74cbcf53c637f434e6cb2af885841de
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/hidden_malloc.c
@@ -0,0 +1,13 @@
+/* run.config
+   COMMENT: Malloc executed by a library function
+*/
+
+#include <limits.h>
+#include <stdlib.h>
+
+int main(int argc, const char **argv) {
+  /* If the second argument of `realpath` is NULL it uses malloc.
+     Make sure that memory layout has been initialized. */
+  char *cwd = realpath(".", NULL);
+  return 0;
+}
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_hidden_malloc.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_hidden_malloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..3a2240a660f8f3d640002528d1807a02651615c7
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_hidden_malloc.c
@@ -0,0 +1,33 @@
+/* Generated by Frama-C */
+#include "stdlib.h"
+char *__gen_e_acsl_literal_string;
+/*@ assigns \result, *((char *)x_1 + (0 ..));
+    assigns \result \from *(x_0 + (0 ..)), *((char *)x_1 + (0 ..));
+    assigns *((char *)x_1 + (0 ..))
+      \from *(x_0 + (0 ..)), *((char *)x_1 + (0 ..));
+ */
+extern int ( /* missing proto */ realpath)(char const *x_0, void *x_1);
+
+void __e_acsl_globals_init(void)
+{
+  __gen_e_acsl_literal_string = ".";
+  __e_acsl_store_block((void *)__gen_e_acsl_literal_string,sizeof("."));
+  __e_acsl_full_init((void *)__gen_e_acsl_literal_string);
+  __e_acsl_mark_readonly((void *)__gen_e_acsl_literal_string);
+  return;
+}
+
+int main(int argc, char const **argv)
+{
+  int __retres;
+  int tmp;
+  __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8);
+  __e_acsl_globals_init();
+  tmp = realpath(__gen_e_acsl_literal_string,(void *)0);
+  char *cwd = (char *)tmp;
+  __retres = 0;
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/hidden_malloc.err.oracle b/src/plugins/e-acsl/tests/runtime/oracle/hidden_malloc.err.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/hidden_malloc.res.oracle b/src/plugins/e-acsl/tests/runtime/oracle/hidden_malloc.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..537cc4f4abfd448619f4698b21c6de8791f80b19
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/hidden_malloc.res.oracle
@@ -0,0 +1,6 @@
+tests/runtime/hidden_malloc.c:11:[kernel] warning: Calling undeclared function realpath. Old style K&R code?
+[e-acsl] beginning translation.
+tests/runtime/hidden_malloc.c:11:[kernel] warning: Neither code nor specification for function realpath, generating default assigns from the prototype
+[e-acsl] translation done in project "e-acsl".
+tests/runtime/hidden_malloc.c:11:[value] warning: Completely invalid destination for assigns clause *((char *)x_1 + (0 ..)).
+                 Ignoring.