From 8b3da8d8c97e6ed1f2d9f3dffe4b42856608d75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= <francois.bobot@cea.fr> Date: Wed, 9 Oct 2019 13:21:10 +0200 Subject: [PATCH] Add conversion from generic floatting point contract to finite one --- Makefile | 1 + headers/header_spec.txt | 2 + .../contract_finite_float.ml | 83 +++++++++++++++++++ .../contract_finite_float.mli | 21 +++++ .../plugin_entry_points/kernel.ml | 10 +++ .../plugin_entry_points/kernel.mli | 3 + src/plugins/wp/wpo.mli | 3 +- tests/float/contract_finite_float.c | 29 +++++++ .../oracle/contract_finite_float.res.oracle | 39 +++++++++ 9 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/kernel_services/ast_transformations/contract_finite_float.ml create mode 100644 src/kernel_services/ast_transformations/contract_finite_float.mli create mode 100644 tests/float/contract_finite_float.c create mode 100644 tests/float/oracle/contract_finite_float.res.oracle diff --git a/Makefile b/Makefile index 72ee2dfc2f0..083de2d3112 100644 --- a/Makefile +++ b/Makefile @@ -612,6 +612,7 @@ KERNEL_CMO=\ src/kernel_services/ast_transformations/filter.cmo \ src/kernel_services/ast_transformations/inline.cmo \ src/kernel_internals/runtime/dump_config.cmo \ + src/kernel_services/ast_transformations/contract_finite_float.cmo \ src/kernel_internals/runtime/special_hooks.cmo \ src/kernel_internals/runtime/messages.cmo diff --git a/headers/header_spec.txt b/headers/header_spec.txt index d1e4b57004f..c5a358290cf 100644 --- a/headers/header_spec.txt +++ b/headers/header_spec.txt @@ -567,6 +567,8 @@ src/kernel_services/ast_queries/logic_typing.mli: CEA_INRIA_LGPL src/kernel_services/ast_queries/logic_utils.ml: CEA_INRIA_LGPL src/kernel_services/ast_queries/logic_utils.mli: CEA_INRIA_LGPL src/kernel_services/ast_transformations/README.md: .ignore +src/kernel_services/ast_transformations/contract_finite_float.ml: CEA_LGPL +src/kernel_services/ast_transformations/contract_finite_float.mli: CEA_LGPL src/kernel_services/ast_transformations/clone.ml: CEA_LGPL src/kernel_services/ast_transformations/clone.mli: CEA_LGPL src/kernel_services/ast_transformations/filter.ml: CEA_LGPL diff --git a/src/kernel_services/ast_transformations/contract_finite_float.ml b/src/kernel_services/ast_transformations/contract_finite_float.ml new file mode 100644 index 00000000000..79a908dd694 --- /dev/null +++ b/src/kernel_services/ast_transformations/contract_finite_float.ml @@ -0,0 +1,83 @@ +(**************************************************************************) +(* *) +(* 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 + +let rec is_infinite_or_nan pred = + match pred.pred_content with + | Pand(a,b) -> is_infinite_or_nan a || is_infinite_or_nan b + | Papp ({l_var_info = { lv_name = ("\\is_plus_infinity" + |"\\is_minus_infinity" + |"\\is_infinite" + |"\\is_NaN")}},[],[_]) -> true + | _ -> false + +let visit = object + inherit Cil.nopCilVisitor + + method! vspec spec = + let requires, behaviors = Extlib.fold_map_opt + (fun acc bhv -> + let exists = List.exists (function + | (Normal,v) -> + is_infinite_or_nan v.ip_content + | _ -> false + ) + bhv.b_post_cond + in + if exists + then + let neg_assumes = + List.map (fun e -> (Logic_const.pnot (e.ip_content))) bhv.b_assumes + in + Logic_const.(new_predicate (pors neg_assumes))::acc + , None + else acc, Some bhv + ) + [] spec.spec_behavior + in + spec.spec_behavior <- behaviors; + begin match requires with + | [] -> () + | _ -> + List.iter + (fun bhv -> + if bhv.b_name = Cil.default_behavior_name then + bhv.b_requires <- requires@bhv.b_requires + ) + spec.spec_behavior + end; + Cil.SkipChildren + +end + +let run ast = + if Kernel.ContractFiniteFloat.get () then + Cil.visitCilFileSameGlobals visit ast + +let transform = + File.register_code_transformation_category "contract_finite_float" + +let () = + File.add_code_transformation_before_cleanup + ~deps:[(module Kernel.ContractFiniteFloat)] + transform run diff --git a/src/kernel_services/ast_transformations/contract_finite_float.mli b/src/kernel_services/ast_transformations/contract_finite_float.mli new file mode 100644 index 00000000000..fa8f3783c35 --- /dev/null +++ b/src/kernel_services/ast_transformations/contract_finite_float.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/kernel_services/plugin_entry_points/kernel.ml b/src/kernel_services/plugin_entry_points/kernel.ml index 8b30799b24b..d8db54e0275 100644 --- a/src/kernel_services/plugin_entry_points/kernel.ml +++ b/src/kernel_services/plugin_entry_points/kernel.ml @@ -1320,6 +1320,16 @@ module Constfold = let help = "fold all constant expressions in the code before analysis" end) +let () = Parameter_customize.set_group normalisation +module ContractFiniteFloat = + False + (struct + let option_name = "-contract-finite-float" + let module_name = "ContractFiniteFloat" + let help = "Add requires in contract to forbid cases that ensures \ + infinite or nan behaviors" + end) + let () = Parameter_customize.set_group normalisation let () = Parameter_customize.do_not_reset_on_copy () module InitializedPaddingLocals = diff --git a/src/kernel_services/plugin_entry_points/kernel.mli b/src/kernel_services/plugin_entry_points/kernel.mli index c971c83111f..3490029a550 100644 --- a/src/kernel_services/plugin_entry_points/kernel.mli +++ b/src/kernel_services/plugin_entry_points/kernel.mli @@ -456,6 +456,9 @@ module SimplifyTrivialLoops: Parameter_sig.Bool module Constfold: Parameter_sig.Bool (** Behavior of option "-constfold" *) +module ContractFiniteFloat: Parameter_sig.Bool + (** Behavior of option "-contract-finite-float" *) + module InitializedPaddingLocals: Parameter_sig.Bool (** Behavior of option "-initialized-padding-locals" *) diff --git a/src/plugins/wp/wpo.mli b/src/plugins/wp/wpo.mli index 580b6469497..9491c8dc3c3 100644 --- a/src/plugins/wp/wpo.mli +++ b/src/plugins/wp/wpo.mli @@ -79,7 +79,8 @@ module VC_Annot : sig type t = { - axioms : Definitions.axioms option ; + axioms + : Definitions.axioms option ; goal : GOAL.t ; tags : Splitter.tag list ; warn : Warning.t list ; diff --git a/tests/float/contract_finite_float.c b/tests/float/contract_finite_float.c new file mode 100644 index 00000000000..07cfa158134 --- /dev/null +++ b/tests/float/contract_finite_float.c @@ -0,0 +1,29 @@ +/* run.config* + OPT: -eva @EVA_CONFIG@ -warn-special-float none -contract-finite-float +*/ + +#include <math.h> + + +/*@ + assigns \result \from x; + behavior normal: + assumes finite_arg: \is_finite(x); + ensures res_finite: \is_finite(\result); + ensures positive_result: \result >= 0.; + ensures equal_magnitude_result: \result == x || \result == -x; + behavior nan: + assumes nan_arg: \is_NaN(x); + ensures res_nan: \is_NaN(\result); + behavior infinite: + assumes infinite_arg: \is_infinite(x); + ensures res_plus_infinity: \is_plus_infinity(\result); +*/ +extern double myfabs(double x); + +volatile double x; + +int main(){ + double z = x; + double y = myfabs(x); +} diff --git a/tests/float/oracle/contract_finite_float.res.oracle b/tests/float/oracle/contract_finite_float.res.oracle new file mode 100644 index 00000000000..88888d6b1f3 --- /dev/null +++ b/tests/float/oracle/contract_finite_float.res.oracle @@ -0,0 +1,39 @@ +[kernel] Parsing tests/float/contract_finite_float.c (with preprocessing) +[kernel] Failure: No kernel function for __builtin_va_copy(11) +[kernel] Current source was: :0 + The full backtrace is: + Raised at file "src/kernel_services/plugin_entry_points/log.ml" (inlined), line 532, characters 24-31 + Called from file "src/kernel_services/plugin_entry_points/log.ml", line 1098, characters 17-55 + Called from file "src/kernel_services/plugin_entry_points/log.ml", line 525, characters 9-23 + Re-raised at file "src/kernel_services/plugin_entry_points/log.ml", line 528, characters 9-16 + Called from file "src/kernel_services/visitors/visitor.ml", line 630, characters 10-68 + Called from file "src/kernel_services/ast_queries/cil.ml", line 1237, characters 15-31 + Called from file "src/kernel_services/ast_queries/cil.ml", line 2742, characters 4-52 + Called from file "src/kernel_services/ast_queries/cil.ml" (inlined), line 5458, characters 16-36 + Called from file "src/kernel_services/ast_queries/cil.ml", line 5461, characters 13-20 + Called from file "list.ml", line 106, characters 12-15 + Called from file "src/kernel_services/ast_queries/cil.ml", line 5108, characters 2-29 + Called from file "src/kernel_services/ast_queries/cil.ml", line 5459, characters 2-359 + Called from file "src/kernel_services/ast_queries/cil.ml", line 1182, characters 19-39 + Called from file "src/kernel_services/ast_queries/cil.ml", line 5492, characters 6-102 + Called from file "src/kernel_services/visitors/visitor.ml" (inlined), line 853, characters 2-45 + Called from file "src/kernel_services/ast_transformations/contract_finite_float.ml", line 35, characters 4-48 + Called from file "src/kernel_services/ast_queries/file.ml", line 1043, characters 2-7 + Called from file "queue.ml", line 105, characters 6-15 + Called from file "src/topological.ml", line 137, characters 18-25 + Called from file "src/kernel_services/ast_queries/file.ml", line 1099, characters 2-36 + Called from file "src/kernel_services/ast_queries/file.ml", line 1567, characters 2-22 + Called from file "src/kernel_services/ast_queries/file.ml", line 1645, characters 4-27 + Called from file "src/kernel_services/ast_data/ast.ml", line 110, characters 2-28 + Called from file "src/kernel_services/ast_data/ast.ml", line 118, characters 53-71 + Called from file "src/kernel_internals/runtime/boot.ml", line 29, characters 6-20 + Called from file "src/kernel_services/cmdline_parameters/cmdline.ml", line 792, characters 2-9 + Called from file "src/kernel_services/cmdline_parameters/cmdline.ml", line 822, characters 18-64 + Called from file "src/kernel_services/cmdline_parameters/cmdline.ml", line 229, characters 4-8 + + Frama-C aborted: internal error. + Please report as 'crash' at http://bts.frama-c.com/. + Your Frama-C version is 19.1+dev (Potassium). + Note that a version and a backtrace alone often do not contain enough + information to understand the bug. Guidelines for reporting bugs are at: + http://bts.frama-c.com/dokuwiki/doku.php?id=mantis:frama-c:bug_reporting_guidelines -- GitLab