From 8a99bf321060f700acda5b73ee25219aa72c6ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr> Date: Tue, 22 Feb 2022 10:12:06 +0100 Subject: [PATCH] [Eva] New file active_behaviors. --- Makefile | 6 +- .../domains/cvalue/cvalue_specification.ml | 6 +- src/plugins/value/engine/transfer_logic.ml | 80 +++---------------- src/plugins/value/engine/transfer_logic.mli | 17 ++-- src/plugins/value/register.ml | 12 +++ src/plugins/value/utils/active_behaviors.ml | 75 +++++++++++++++++ src/plugins/value/utils/active_behaviors.mli | 29 +++++++ 7 files changed, 135 insertions(+), 90 deletions(-) create mode 100644 src/plugins/value/utils/active_behaviors.ml create mode 100644 src/plugins/value/utils/active_behaviors.mli diff --git a/Makefile b/Makefile index 2f24f05df08..531ba1bf1fa 100644 --- a/Makefile +++ b/Makefile @@ -865,7 +865,7 @@ endif PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode self parameters \ utils/eva_audit utils/eva_perf utils/eva_annotations \ utils/eva_dynamic utils/eva_utils utils/red_statuses \ - utils/mark_noresults \ + utils/active_behaviors utils/mark_noresults \ utils/widen_hints_ext utils/widen \ partitioning/split_return \ partitioning/per_stmt_slevel \ @@ -900,17 +900,17 @@ PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode self parameters \ domains/cvalue/builtins_float domains/cvalue/builtins_split \ domains/inout_domain \ legacy/eval_terms legacy/eval_annots \ - domains/powerset engine/transfer_logic \ domains/cvalue/cvalue_transfer domains/cvalue/cvalue_init \ domains/cvalue/cvalue_specification \ domains/cvalue/cvalue_domain \ utils/eva_results \ + domains/powerset \ partitioning/auto_loop_unroll \ partitioning/partition partitioning/partitioning_parameters \ partitioning/partitioning_index partitioning/trace_partitioning \ engine/recursion engine/function_calls \ engine/subdivided_evaluation engine/evaluation engine/abstractions \ - engine/transfer_stmt engine/transfer_specification \ + engine/transfer_logic engine/transfer_stmt engine/transfer_specification \ engine/mem_exec engine/iterator engine/initialization \ engine/compute_functions engine/analysis register \ domains/taint_domain \ diff --git a/src/plugins/value/domains/cvalue/cvalue_specification.ml b/src/plugins/value/domains/cvalue/cvalue_specification.ml index 4336ecdaf40..aebbdbd39bc 100644 --- a/src/plugins/value/domains/cvalue/cvalue_specification.ml +++ b/src/plugins/value/domains/cvalue/cvalue_specification.ml @@ -22,8 +22,6 @@ open Cil_types -module AB = Transfer_logic.ActiveBehaviors - (* Eval: under-approximation of the term. Note that ACSL states that assigns clauses are evaluated in the pre-state. We skip [\result]: it is meaningless when evaluating the 'assigns' part, @@ -114,7 +112,7 @@ let check_fct_assigns kf ab ~pre_state found_froms = let link zones = List.fold_left Zone.link Zone.bottom zones in let outputs = Function_Froms.outputs found_froms in let check_for_behavior b = - let activity = AB.is_active ab b in + let activity = Active_behaviors.is_active ab b in match activity with | False -> () | True | Unknown -> @@ -187,7 +185,7 @@ let verify_assigns_from kf ~pre froms = | Eval_terms.False -> Alarmset.False | Eval_terms.Unknown -> Alarmset.Unknown in - let ab = AB.create eval_predicate funspec in + let ab = Active_behaviors.create eval_predicate funspec in check_fct_assigns kf ab ~pre_state:pre froms;; Db.Value.verify_assigns_froms := verify_assigns_from;; diff --git a/src/plugins/value/engine/transfer_logic.ml b/src/plugins/value/engine/transfer_logic.ml index 124437be116..d56f52ae0bb 100644 --- a/src/plugins/value/engine/transfer_logic.ml +++ b/src/plugins/value/engine/transfer_logic.ml @@ -141,68 +141,6 @@ let create_conjunction l= in Logic_const.(List.fold_right (fun p1 p2 -> pand ?loc (p1, p2)) (List.map pred_of_id_pred l) ptrue) -(* -------------------------- Active behaviors ------------------------------ *) - -module ActiveBehaviors = struct - - type t = { - funspec: funspec; - is_active: funbehavior -> Alarmset.status - } - - module HashBehaviors = Hashtbl.Make( - struct - type t = funbehavior - let equal b1 b2 = b1.b_name = b2.b_name - let hash b = Hashtbl.hash b.b_name - end) - - let is_active eval_predicate b = - let assumes = create_conjunction b.b_assumes in - eval_predicate assumes - - let create eval_predicate funspec = - let h = HashBehaviors.create 3 in - let is_active = fun b -> - try HashBehaviors.find h b - with Not_found -> - let active = is_active eval_predicate b in - HashBehaviors.add h b active; - active - in - { is_active; funspec } - - let is_active ab behavior = ab.is_active behavior - - let active_behaviors ab = - List.filter - (fun b -> is_active ab b != Alarmset.False) - ab.funspec.spec_behavior - - let is_active_from_name ab name = - try - let list = ab.funspec.spec_behavior in - let behavior = List.find (fun b' -> b'.b_name = name) list in - is_active ab behavior - (* This case happens for behaviors of statement contract, that are not - handled by this module. *) - with Not_found -> Alarmset.Unknown -end - -let () = - Db.Value.valid_behaviors := - (fun kf state -> - let funspec = Annotations.funspec kf in - let eval_predicate pred = - match Eval_terms.(eval_predicate (env_pre_f ~pre:state ()) pred) with - | Eval_terms.True -> Alarmset.True - | Eval_terms.False -> Alarmset.False - | Eval_terms.Unknown -> Alarmset.Unknown - in - let ab = ActiveBehaviors.create eval_predicate funspec in - ActiveBehaviors.active_behaviors ab - ) - let ip_from_precondition kf call_ki b pre = let ip_precondition = Property.ip_of_requires kf Kglobal b pre in match call_ki with @@ -269,22 +207,22 @@ module type S = sig type state type states - val create: state -> kernel_function -> ActiveBehaviors.t - val create_from_spec: state -> spec -> ActiveBehaviors.t + val create: state -> kernel_function -> Active_behaviors.t + val create_from_spec: state -> spec -> Active_behaviors.t val check_fct_preconditions_for_behaviors: kinstr -> kernel_function -> behavior list -> Alarmset.status -> states -> states val check_fct_preconditions: - kinstr -> kernel_function -> ActiveBehaviors.t -> state -> states or_bottom + kinstr -> kernel_function -> Active_behaviors.t -> state -> states or_bottom val check_fct_postconditions_for_behaviors: kernel_function -> behavior list -> Alarmset.status -> pre_state:state -> post_states:states -> result:varinfo option -> states val check_fct_postconditions: - kernel_function -> ActiveBehaviors.t -> termination_kind -> + kernel_function -> Active_behaviors.t -> termination_kind -> pre_state:state -> post_states:states -> result:varinfo option -> states or_bottom @@ -292,7 +230,7 @@ module type S = sig val interp_annot: limit:int -> record:bool -> - kernel_function -> ActiveBehaviors.t -> stmt -> code_annotation -> + kernel_function -> Active_behaviors.t -> stmt -> code_annotation -> initial_state:state -> states -> states end @@ -344,7 +282,7 @@ module Make let create_from_spec pre funspec = let eval_predicate = Domain.evaluate_predicate (pre_env ~pre) pre in - ActiveBehaviors.create eval_predicate funspec + Active_behaviors.create eval_predicate funspec let create init_state kf = let funspec = Annotations.funspec kf in @@ -537,7 +475,7 @@ module Make to help reduce the final state. *) let check_fct_postconditions kf ab kind ~pre_state ~post_states ~result = let behaviors = Annotations.behaviors kf in - let is_active = ActiveBehaviors.is_active ab in + let is_active = Active_behaviors.is_active ab in let states = check_fct_postconditions_of_behaviors kf behaviors is_active kind ~per_behavior:false @@ -583,7 +521,7 @@ module Make let check_fct_preconditions call_ki kf ab init_state = let init_states = States.singleton init_state in let behaviors = Annotations.behaviors kf in - let is_active = ActiveBehaviors.is_active ab in + let is_active = Active_behaviors.is_active ab in let states = check_fct_preconditions_of_behaviors call_ki kf ~per_behavior:false behaviors is_active init_states @@ -625,7 +563,7 @@ module Make | [] -> `True | behavs -> let aux acc b = - match ActiveBehaviors.is_active_from_name ab b with + match Active_behaviors.is_active_from_name ab b with | Alarmset.True -> `True | Alarmset.Unknown -> if acc = `True then `True else `Unknown | Alarmset.False -> acc diff --git a/src/plugins/value/engine/transfer_logic.mli b/src/plugins/value/engine/transfer_logic.mli index 2512aac64e2..e328d5a9c0b 100644 --- a/src/plugins/value/engine/transfer_logic.mli +++ b/src/plugins/value/engine/transfer_logic.mli @@ -23,13 +23,6 @@ open Cil_types open Eval -module ActiveBehaviors : sig - type t - val is_active: t -> behavior -> Alarmset.status - val active_behaviors: t -> behavior list - val create: (predicate -> Alarmset.status) -> spec -> t -end - (* Marks all behaviors of the list as inactive. *) val process_inactive_behaviors: kinstr -> kernel_function -> behavior list -> unit @@ -38,22 +31,22 @@ module type S = sig type state type states - val create: state -> kernel_function -> ActiveBehaviors.t - val create_from_spec: state -> spec -> ActiveBehaviors.t + val create: state -> kernel_function -> Active_behaviors.t + val create_from_spec: state -> spec -> Active_behaviors.t val check_fct_preconditions_for_behaviors: kinstr -> kernel_function -> behavior list -> Alarmset.status -> states -> states val check_fct_preconditions: - kinstr -> kernel_function -> ActiveBehaviors.t -> state -> states or_bottom + kinstr -> kernel_function -> Active_behaviors.t -> state -> states or_bottom val check_fct_postconditions_for_behaviors: kernel_function -> behavior list -> Alarmset.status -> pre_state:state -> post_states:states -> result:varinfo option -> states val check_fct_postconditions: - kernel_function -> ActiveBehaviors.t -> termination_kind -> + kernel_function -> Active_behaviors.t -> termination_kind -> pre_state:state -> post_states:states -> result:varinfo option -> states or_bottom @@ -61,7 +54,7 @@ module type S = sig val interp_annot: limit:int -> record:bool -> - kernel_function -> ActiveBehaviors.t -> stmt -> code_annotation -> + kernel_function -> Active_behaviors.t -> stmt -> code_annotation -> initial_state:state -> states -> states end diff --git a/src/plugins/value/register.ml b/src/plugins/value/register.ml index c57f8f46daa..c1e1695ae85 100644 --- a/src/plugins/value/register.ml +++ b/src/plugins/value/register.ml @@ -140,6 +140,17 @@ let eval_predicate ~pre ~here p = | False -> Property_status.False_if_reachable | Unknown -> Property_status.Dont_know +let valid_behaviors kf state = + let funspec = Annotations.funspec kf in + let eval_predicate pred = + match Eval_terms.(eval_predicate (env_pre_f ~pre:state ()) pred) with + | Eval_terms.True -> Alarmset.True + | Eval_terms.False -> Alarmset.False + | Eval_terms.Unknown -> Alarmset.Unknown + in + let ab = Active_behaviors.create eval_predicate funspec in + Active_behaviors.active_behaviors ab + let () = (* Pretty-printing *) Db.Value.use_spec_instead_of_definition := use_spec_instead_of_definition; @@ -150,6 +161,7 @@ let () = Db.Value.access_location := access_value_of_location; Db.Value.access_expr := access_value_of_expr; Db.Value.Logic.eval_predicate := eval_predicate; + Db.Value.valid_behaviors := valid_behaviors; Db.From.find_deps_term_no_transitivity_state := find_deps_term_no_transitivity_state; diff --git a/src/plugins/value/utils/active_behaviors.ml b/src/plugins/value/utils/active_behaviors.ml new file mode 100644 index 00000000000..bd8599329f8 --- /dev/null +++ b/src/plugins/value/utils/active_behaviors.ml @@ -0,0 +1,75 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2022 *) +(* 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 create_conjunction l = + let open Logic_const in + let loc = match l with + | [] -> None + | p :: _ -> Some (pred_of_id_pred p).pred_loc + in + let predicates = List.map pred_of_id_pred l in + List.fold_right (fun p1 p2 -> pand ?loc (p1, p2)) predicates ptrue + +type t = { + funspec: funspec; + is_active: funbehavior -> Alarmset.status +} + +module HashBehaviors = Hashtbl.Make( + struct + type t = funbehavior + let equal b1 b2 = b1.b_name = b2.b_name + let hash b = Hashtbl.hash b.b_name + end) + +let is_active eval_predicate b = + let assumes = create_conjunction b.b_assumes in + eval_predicate assumes + +let create eval_predicate funspec = + let h = HashBehaviors.create 3 in + let is_active = fun b -> + try HashBehaviors.find h b + with Not_found -> + let active = is_active eval_predicate b in + HashBehaviors.add h b active; + active + in + { is_active; funspec } + +let is_active ab behavior = ab.is_active behavior + +let active_behaviors ab = + List.filter + (fun b -> is_active ab b != Alarmset.False) + ab.funspec.spec_behavior + +let is_active_from_name ab name = + try + let list = ab.funspec.spec_behavior in + let behavior = List.find (fun b' -> b'.b_name = name) list in + is_active ab behavior + (* This case happens for behaviors of statement contract, that are not + handled by this module. *) + with Not_found -> Alarmset.Unknown diff --git a/src/plugins/value/utils/active_behaviors.mli b/src/plugins/value/utils/active_behaviors.mli new file mode 100644 index 00000000000..5ca99b054e5 --- /dev/null +++ b/src/plugins/value/utils/active_behaviors.mli @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2022 *) +(* 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 + +type t +val is_active: t -> behavior -> Alarmset.status +val is_active_from_name: t -> string -> Alarmset.status +val active_behaviors: t -> behavior list +val create: (predicate -> Alarmset.status) -> spec -> t -- GitLab