From e7bee952d3d63316c0b8b938b48ab922b80deb17 Mon Sep 17 00:00:00 2001 From: Allan Blanchard <allan.blanchard@cea.fr> Date: Wed, 23 Oct 2019 11:36:11 +0200 Subject: [PATCH] [Builtin] Module for allocation contracts components --- headers/header_spec.txt | 2 + src/plugins/builtin/Makefile.in | 1 + src/plugins/builtin/stdlib/basic_alloc.ml | 70 ++++++++++++++++++++ src/plugins/builtin/stdlib/basic_alloc.mli | 35 ++++++++++ src/plugins/builtin/stdlib/malloc.ml | 77 +++++++--------------- 5 files changed, 133 insertions(+), 52 deletions(-) create mode 100644 src/plugins/builtin/stdlib/basic_alloc.ml create mode 100644 src/plugins/builtin/stdlib/basic_alloc.mli diff --git a/headers/header_spec.txt b/headers/header_spec.txt index 7eb1cb9bbec..fefa4de4484 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/stdlib/basic_alloc.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/builtin/stdlib/basic_alloc.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/stdlib/malloc.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/stdlib/malloc.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/builtin/string/memcmp.ml: CEA_LGPL_OR_PROPRIETARY diff --git a/src/plugins/builtin/Makefile.in b/src/plugins/builtin/Makefile.in index ec3691bfd99..d631ccb7f8f 100644 --- a/src/plugins/builtin/Makefile.in +++ b/src/plugins/builtin/Makefile.in @@ -37,6 +37,7 @@ SRC_STRING:= \ SRC_STRING:=$(addprefix string/, $(SRC_STRING)) SRC_STDLIB:= \ + basic_alloc \ malloc SRC_STDLIB:=$(addprefix stdlib/, $(SRC_STDLIB)) diff --git a/src/plugins/builtin/stdlib/basic_alloc.ml b/src/plugins/builtin/stdlib/basic_alloc.ml new file mode 100644 index 00000000000..6e38a02f6bb --- /dev/null +++ b/src/plugins/builtin/stdlib/basic_alloc.ml @@ -0,0 +1,70 @@ +(**************************************************************************) +(* *) +(* 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 Logic_const +open Cil_types + +let pis_allocable ?loc size = + pallocable ?loc (here_label, size) + +let is_allocable ?loc size = + let p = pis_allocable ?loc size in + new_predicate { p with pred_name = [ "allocable" ]} + +let isnt_allocable ?loc size = + let p = pnot ?loc (pis_allocable ?loc size) in + new_predicate { p with pred_name = [ "allocable" ]} + +let heap_status () = + let heap_status = Globals.Vars.find_from_astinfo "__fc_heap_status" VGlobal in + Basic_blocks.cvar_to_tvar (heap_status) + +let assigns_result ?loc typ deps = + let heap_status = new_identified_term (heap_status ()) in + let deps = match deps with + | [] -> [] + | l -> heap_status :: (List.map new_identified_term l) + in + let result = new_identified_term (tresult ?loc typ) in + result, From deps + +let assigns_heap deps = + let heap_status = new_identified_term (heap_status ()) in + let deps = List.map new_identified_term deps in + heap_status, From (heap_status :: deps) + +let allocates_nothing () = + FreeAlloc([],[]) + +let allocates_result ?loc t = + FreeAlloc ([], [new_identified_term (tresult ?loc t)]) + +let fresh_result ?loc typ size = + let result = tresult ?loc typ in + let p = pfresh ?loc (old_label, here_label, result, size) in + new_predicate { p with pred_name = [ "fresh_result" ] } + +let null_result ?loc typ = + let tresult = tresult ?loc typ in + let tnull = term ?loc Tnull (Ctype typ) in + let p = prel ?loc (Req, tresult, tnull) in + new_predicate { p with pred_name = [ "null_result" ] } diff --git a/src/plugins/builtin/stdlib/basic_alloc.mli b/src/plugins/builtin/stdlib/basic_alloc.mli new file mode 100644 index 00000000000..0ff9e7864da --- /dev/null +++ b/src/plugins/builtin/stdlib/basic_alloc.mli @@ -0,0 +1,35 @@ +(**************************************************************************) +(* *) +(* 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 Cil_types + +val is_allocable: ?loc:location -> term -> identified_predicate +val isnt_allocable: ?loc:location -> term -> identified_predicate + +val assigns_result: ?loc:location -> typ -> term list -> from +val assigns_heap: term list -> from + +val allocates_nothing: unit -> allocation +val allocates_result: ?loc:location -> typ -> allocation + +val fresh_result: ?loc:location -> typ -> term -> identified_predicate +val null_result: ?loc:location -> typ -> identified_predicate diff --git a/src/plugins/builtin/stdlib/malloc.ml b/src/plugins/builtin/stdlib/malloc.ml index 465d4bc817f..212f7b4a102 100644 --- a/src/plugins/builtin/stdlib/malloc.ml +++ b/src/plugins/builtin/stdlib/malloc.ml @@ -21,82 +21,55 @@ (**************************************************************************) open Basic_blocks +open Basic_alloc 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 = +let generate_requires loc ptr_type size = [ new_predicate - { (pcorrect_len_bytes ~loc ptr_type len) + { (pcorrect_len_bytes ~loc ptr_type size) 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 +let generate_global_assigns loc ptr_type size = + let assigns_result = assigns_result ~loc ptr_type [ size ] in + let assigns_heap = assigns_heap [ size ] 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 +let make_behavior_allocation loc ptr_type size = + let assumes = [ is_allocable ~loc size ] in + let assigns = generate_global_assigns loc ptr_type size in + let alloc = allocates_result ~loc ptr_type in + let ensures = [ Normal, fresh_result ~loc ptr_type size ] 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 +let make_behavior_no_allocation loc ptr_type size = + let assumes = [ isnt_allocable ~loc size ] in + let assigns = Writes [assigns_result ~loc ptr_type []] in + let ensures = [ Normal, null_result ~loc ptr_type ] in + let alloc = allocates_nothing () 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 + let (csize) = match Cil.getFormalsDecl vi with + | [ size ] -> size | _ -> 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 + let size = tlogic_coerce ~loc (cvar_to_tvar csize) Linteger in + let requires = generate_requires loc (Ctype (ptr_of alloc_typ)) size in + let assigns = generate_global_assigns loc (ptr_of alloc_typ) size in + let alloc = allocates_result ~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 + make_behavior_allocation loc (ptr_of alloc_typ) size ; + make_behavior_no_allocation loc (ptr_of alloc_typ) size ] () let generate_prototype alloc_t = let name = function_name ^ "_" ^ (string_of_typ alloc_t) in let params = [ - ("len", size_t (), []) + ("size", size_t (), []) ] in name, (TFun((ptr_of alloc_t), Some params, false, [])) -- GitLab