From e9cef177c3e85b97bf8f5b9d1748201b7c91e1a9 Mon Sep 17 00:00:00 2001 From: Allan Blanchard <allan.blanchard@cea.fr> Date: Tue, 22 Oct 2019 17:52:34 +0200 Subject: [PATCH] [Builtin] Adds malloc --- headers/header_spec.txt | 2 + src/plugins/builtin/Makefile.in | 2 +- src/plugins/builtin/builtin_builder.ml | 6 ++ src/plugins/builtin/malloc.ml | 131 +++++++++++++++++++++++++ src/plugins/builtin/malloc.mli | 21 ++++ src/plugins/builtin/transform.ml | 18 ++-- 6 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 src/plugins/builtin/malloc.ml create mode 100644 src/plugins/builtin/malloc.mli diff --git a/headers/header_spec.txt b/headers/header_spec.txt index 9cf5277d18f..093fdc6dc87 100644 --- a/headers/header_spec.txt +++ b/headers/header_spec.txt @@ -937,6 +937,8 @@ src/plugins/builtin/builtin_builder.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/builtin_builder.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/configure.ac: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/Makefile.in: CEA_LGPL_OR_PROPRIETARY +src/plugins/builtin/malloc.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/builtin/malloc.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/memcmp.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/memcmp.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/memcpy.ml: CEA_LGPL_OR_PROPRIETARY diff --git a/src/plugins/builtin/Makefile.in b/src/plugins/builtin/Makefile.in index 70d49bb5ece..09306b9c327 100644 --- a/src/plugins/builtin/Makefile.in +++ b/src/plugins/builtin/Makefile.in @@ -38,7 +38,7 @@ PLUGIN_ENABLE := @ENABLE_BUILTIN@ PLUGIN_NAME := Builtin PLUGIN_CMI := PLUGIN_CMO := basic_blocks options builtin_builder transform \ - memcpy memcmp memmove memset \ + malloc memcpy memcmp memmove memset \ register PLUGIN_DISTRIBUTED := $(PLUGIN_ENABLE) PLUGIN_DISTRIB_EXTERNAL:= Makefile.in configure.ac configure diff --git a/src/plugins/builtin/builtin_builder.ml b/src/plugins/builtin/builtin_builder.ml index c3c201351ed..05294da6d68 100644 --- a/src/plugins/builtin/builtin_builder.ml +++ b/src/plugins/builtin/builtin_builder.ml @@ -92,6 +92,12 @@ module Make_builtin (G: Generator_sig) = struct let kf = Globals.Functions.get fd.svar in let spec = generate_spec key fd loc in Annotations.add_behaviors Options.emitter kf spec.spec_behavior ; + List.iter + (Annotations.add_complete Options.emitter kf) + spec.spec_complete_behaviors ; + List.iter + (Annotations.add_disjoint Options.emitter kf) + spec.spec_disjoint_behaviors ; fd let get_override key = diff --git a/src/plugins/builtin/malloc.ml b/src/plugins/builtin/malloc.ml new file mode 100644 index 00000000000..465d4bc817f --- /dev/null +++ b/src/plugins/builtin/malloc.ml @@ -0,0 +1,131 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Basic_blocks +open Cil_types +open Logic_const + +let function_name = "malloc" + +let fc_heap_status () = + Globals.Vars.find_from_astinfo "__fc_heap_status" VGlobal + +let generate_requires loc ptr_type len = + [ new_predicate + { (pcorrect_len_bytes ~loc ptr_type len) + with pred_name = ["aligned_end"] } ] + +let generate_global_assigns loc ptr_type len = + let len = new_identified_term len in + let res = new_identified_term (tresult ~loc ptr_type) in + let hs = new_identified_term (cvar_to_tvar (fc_heap_status ())) in + let assigns_result = res, From [ len ; hs ] in + let assigns_heap = hs, From [ len ; hs ] in + Writes [ assigns_result ; assigns_heap ] + +let is_allocable loc len = + pallocable ~loc (here_label, len) + +let allocation_assumes loc len = + [ new_predicate (is_allocable loc len) ] + +let allocation loc ptr_type = + FreeAlloc ([], [new_identified_term (tresult ~loc ptr_type)]) + +let allocation_ensures loc ptr_type len = + let result = tresult ~loc ptr_type in + let fresh = pfresh ~loc (old_label, here_label, result, len) in + [ Normal, new_predicate fresh ] + +let make_behavior_allocation loc ptr_type len = + let assumes = allocation_assumes loc len in + let assigns = generate_global_assigns loc ptr_type len in + let alloc = allocation loc ptr_type in + let ensures = allocation_ensures loc ptr_type len in + make_behavior ~name:"allocation" ~assumes ~assigns ~alloc ~ensures () + +let no_allocation_assumes loc len = + [ new_predicate (pnot ~loc (is_allocable loc len)) ] + +let no_allocation_result loc ptr_type = + let tresult = tresult ~loc ptr_type in + let tnull = term ~loc Tnull (Ctype ptr_type) in + [ Normal, new_predicate (prel ~loc (Req, tresult, tnull)) ] + +let make_behavior_no_allocation loc ptr_type len = + let assumes = no_allocation_assumes loc len in + let assigns = Writes [new_identified_term (tresult ~loc ptr_type), From []] in + let ensures = no_allocation_result loc ptr_type in + let alloc = FreeAlloc([],[]) in + make_behavior ~name:"no_allocation" ~assumes ~assigns ~ensures ~alloc () + +let generate_spec alloc_typ { svar = vi } loc = + let (clen) = match Cil.getFormalsDecl vi with + | [ len ] -> len + | _ -> assert false + in + let len = tlogic_coerce ~loc (cvar_to_tvar clen) Linteger in + let requires = generate_requires loc (Ctype (ptr_of alloc_typ)) len in + let assigns = generate_global_assigns loc (ptr_of alloc_typ) len in + let alloc = allocation loc (ptr_of alloc_typ) in + make_funspec [ + make_behavior ~requires ~assigns ~alloc () ; + make_behavior_allocation loc (ptr_of alloc_typ) len ; + make_behavior_no_allocation loc (ptr_of alloc_typ) len + ] () + +let generate_prototype alloc_t = + let name = function_name ^ "_" ^ (string_of_typ alloc_t) in + let params = [ + ("len", size_t (), []) + ] in + name, (TFun((ptr_of alloc_t), Some params, false, [])) + +let well_typed_call ret args = + match ret, args with + | Some ret, [ _ ] -> Cil.isPointerType (Cil.typeOfLval ret) + | _ -> false + +let key_from_call ret _ = + match ret with + | Some ret -> + let ret_t = Cil.unrollTypeDeep (Cil.typeOfLval ret) in + let ret_t = Cil.type_remove_qualifier_attributes_deep ret_t in + Cil.typeOf_pointed ret_t + | None -> assert false + +let retype_args _typ args = args +let args_for_original _typ fd = + List.map Cil.evar fd.sformals + +let () = Transform.register (module struct + module Hashtbl = Cil_datatype.Typ.Hashtbl + type override_key = typ + + let function_name = function_name + let well_typed_call = well_typed_call + let key_from_call = key_from_call + let retype_args = retype_args + let generate_prototype = generate_prototype + let generate_spec = generate_spec + let args_for_original = args_for_original + end) diff --git a/src/plugins/builtin/malloc.mli b/src/plugins/builtin/malloc.mli new file mode 100644 index 00000000000..fa8f3783c35 --- /dev/null +++ b/src/plugins/builtin/malloc.mli @@ -0,0 +1,21 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) diff --git a/src/plugins/builtin/transform.ml b/src/plugins/builtin/transform.ml index c501c73ee29..71942f21e45 100644 --- a/src/plugins/builtin/transform.ml +++ b/src/plugins/builtin/transform.ml @@ -139,20 +139,24 @@ let compute_call_preconditions_statuses kf = | _ -> assert false let compute_postconditions_statuses kf = - let open Extlib in let posts bhv = - let active = [] in - let ensures = Property.ip_ensures_of_behavior kf Kglobal bhv in - let assigns = Property.ip_assigns_of_behavior ~active kf Kglobal bhv in - let froms = Property.ip_from_of_behavior ~active kf Kglobal bhv in - List.iter validate_property (ensures @ (list_of_opt assigns) @ froms) + List.iter validate_property + (Property.ip_post_cond_of_behavior kf ~active:[] Kglobal bhv) in Annotations.iter_behaviors (fun _ -> posts) kf +let compute_comp_disj_statuses kf = + let open Property in + let comps c = validate_property (ip_of_complete kf Kglobal ~active:[] c) in + let disjs d = validate_property (ip_of_disjoint kf Kglobal ~active:[] d) in + Annotations.iter_complete (fun _ -> comps) kf ; + Annotations.iter_disjoint (fun _ -> disjs) kf + let compute_statuses_all_kfs () = let kfs = get_kfs () in List.iter compute_call_preconditions_statuses kfs ; - List.iter compute_postconditions_statuses kfs + List.iter compute_postconditions_statuses kfs ; + List.iter compute_comp_disj_statuses kfs let transform file = Visitor.visitFramacFile (new transformer) file ; -- GitLab