From 299af05bce73c4a4ba0e0dfc700eb979825c2c79 Mon Sep 17 00:00:00 2001
From: Valentin Perrelle <valentin.perrelle@cea.fr>
Date: Mon, 20 Sep 2021 17:33:59 +0200
Subject: [PATCH] [Eva] api: Functions evaluations must now be done in one step

---
 src/plugins/value/Eva.mli           |  8 ++++-
 src/plugins/value/utils/results.ml  | 56 ++++++++++++++++-------------
 src/plugins/value/utils/results.mli |  8 ++++-
 3 files changed, 46 insertions(+), 26 deletions(-)

diff --git a/src/plugins/value/Eva.mli b/src/plugins/value/Eva.mli
index 71b28373ba5..0fc464a048d 100644
--- a/src/plugins/value/Eva.mli
+++ b/src/plugins/value/Eva.mli
@@ -41,6 +41,11 @@ module Results: sig
   type error = Bottom | Top | DisabledDomain
   type 'a result = ('a,error) Result.t
   
+  val string_of_error : error -> string
+  val pretty_error : Format.formatter -> error -> unit
+  val pretty_result : (Format.formatter -> 'a -> unit) ->
+    Format.formatter -> 'a result -> unit
+  
   (* Control point selection *)
   val at_start : request
   val at_end : request
@@ -72,11 +77,12 @@ module Results: sig
   
   val eval_address : Cil_types.lval -> request -> lvaluation
   
+  val eval_callee : Cil_types.exp -> request -> Cil_types.kernel_function list result (* Ignores non-function values; exp must come from Cil Call constructor and are restricted to lvalues with no offset *)
+  
   (* Value conversion *)
   val as_int : evaluation -> int result
   val as_integer : evaluation -> Integer.t result
   val as_float : evaluation -> float result
-  val as_functions : evaluation -> Cil_types.kernel_function list result (* Ignores non-function values *)
   val as_ival : evaluation -> Ival.t result
   val as_fval : evaluation -> Fval.t result
   val as_cvalue : evaluation -> Cvalue.V.t result
diff --git a/src/plugins/value/utils/results.ml b/src/plugins/value/utils/results.ml
index 7871300ab7a..48189f931d4 100644
--- a/src/plugins/value/utils/results.ml
+++ b/src/plugins/value/utils/results.ml
@@ -20,12 +20,14 @@
 (*                                                                        *)
 (**************************************************************************)
 
+open Bottom.Type
+
 type 'a or_top_bottom = 'a Bottom.Top.or_top_bottom
 
-let (>>>-) t f = match t with
+let (>>>-:) t f = match t with
   | `Top -> `Top
   | `Bottom  -> `Bottom
-  | `Value t -> f t
+  | `Value t -> `Value (f t)
 
 module Callstack = Value_types.Callstack
 
@@ -49,6 +51,17 @@ type request = {
 type error = Bottom | Top | DisabledDomain
 type 'a result = ('a,error) Result.t
 
+let string_of_error = function
+  | Bottom -> "The computed state is bottom"
+  | Top -> "The computed state is Top"
+  | DisabledDomain -> "The required domain is disabled"
+
+let pretty_error fmt error =
+  Format.pp_print_string fmt (string_of_error error)
+let pretty_result f fmt r =
+  Result.fold ~ok:(f fmt) ~error:(pretty_error fmt) r
+
+
 (* Building requests *)
 
 let make control_point = {
@@ -338,9 +351,15 @@ struct
     let eval state = A.Eval.lvaluate ~for_writing:false state lval in
     Response.map eval (get req)
 
-  (* Conversion *)
+  let eval_callee exp req =
+    let join = (@)
+    and extract state =
+      let r,_alarms = A.Eval.eval_function_exp exp state in
+      r >>>-: List.map fst
+    in
+    get req |> Response.map_join' extract join |> convert
 
-  open Bottom.Type
+  (* Conversion *)
 
   let extract_value : type c. c evaluation -> (value or_bottom, c) Response.t =
     function
@@ -359,19 +378,10 @@ struct
     | Some get ->
       let join = Main_values.CVal.join in
       let extract value =
-        (value >>-: get :> 'a or_top_bottom)
+        value >>>-: get
       in
       extract_value res |> Response.map_join' extract join |> convert
 
-  let as_functions : type c. c evaluation ->
-    Cil_types.kernel_function list result =
-    fun res ->
-    let join = (@)
-    and extract value =
-      value >>>- fun v -> (fst (A.Val.resolve_functions v) :> 'a or_top_bottom)
-    in
-    extract_value res |> Response.map_join' extract join |> convert
-
   let extract_loc : type c. c lvaluation -> (location or_bottom, c) Response.t =
     fun r ->
     let extract (x, _alarms) = x >>-: (fun (_valuation,loc,_typ) -> loc) in
@@ -390,7 +400,7 @@ struct
         assert (Int_Base.equal loc2.size size);
         make_loc loc size
       and extract loc =
-        (loc  >>-: get >>-: Precise_locs.imprecise_location :> 'a or_top_bottom)
+        loc  >>>-: get >>>-: Precise_locs.imprecise_location
       in
       extract_loc res |> Response.map_join' extract join |> convert
 
@@ -402,7 +412,7 @@ struct
     | Some get ->
       let join = Locations.Zone.join
       and extract loc =
-        (loc  >>-: get >>-: Precise_locs.enumerate_valid_bits Read :> 'a or_top_bottom)
+        loc  >>>-: get >>>-: Precise_locs.enumerate_valid_bits Read
       in
       extract_loc res |> Response.map_join' extract join |> convert
 
@@ -411,7 +421,7 @@ struct
     | `LValue r ->
       let join = (&&)
       and extract (x, _alarms) =
-        (x >>-: (fun (_valuation,fv) -> fv.Eval.initialized) :> 'a or_top_bottom)
+        x >>>-: (fun (_valuation,fv) -> fv.Eval.initialized)
       in
       begin match Response.map_join' extract join r with
         | `Bottom | `Top -> false
@@ -442,7 +452,7 @@ struct
 
   let is_bottom : type c. c evaluation -> bool =
     fun res ->
-    let extract (x,_) = (x >>-: fun _ -> () :> unit or_top_bottom) in
+    let extract (x,_) = x >>>-: fun _ -> () in
     let join () () = () in
     let r = match res with
       | `LValue r ->
@@ -490,8 +500,6 @@ sig
   type 'a evaluation
   type restriction
   val as_cvalue : 'callstack evaluation -> Main_values.CVal.t result
-  val as_functions : 'callstack evaluation ->
-    Cil_types.kernel_function list result
   val as_location : 'callstack lvaluation -> Locations.location result
   val as_zone : 'callstack lvaluation -> Locations.Zone.t result
   val is_initialized : 'callstack evaluation -> bool
@@ -561,6 +569,10 @@ let eval_address lval req =
       let v = lval
     end : Lvaluation)
 
+let eval_callee exp req =
+  let module M = Make () in
+  M.eval_callee exp req
+
 (* Value conversion *)
 
 let as_cvalue evaluation =
@@ -589,10 +601,6 @@ let as_float evaluation =
   with Fval.Not_Singleton_Float ->
     Result.error Top
 
-let as_functions evaluation =
-  let module E = (val evaluation : Evaluation) in
-  E.as_functions E.v
-
 let as_integer evaluation =
   try
     Result.map Ival.project_int (as_ival evaluation)
diff --git a/src/plugins/value/utils/results.mli b/src/plugins/value/utils/results.mli
index 870feaea2b9..17fb9dda5a7 100644
--- a/src/plugins/value/utils/results.mli
+++ b/src/plugins/value/utils/results.mli
@@ -39,6 +39,11 @@ type lvaluation
 type error = Bottom | Top | DisabledDomain
 type 'a result = ('a,error) Result.t
 
+val string_of_error : error -> string
+val pretty_error : Format.formatter -> error -> unit
+val pretty_result : (Format.formatter -> 'a -> unit) ->
+  Format.formatter -> 'a result -> unit
+
 (* Control point selection *)
 val at_start : request
 val at_end : request
@@ -70,11 +75,12 @@ val eval_exp : Cil_types.exp -> request -> evaluation
 
 val eval_address : Cil_types.lval -> request -> lvaluation
 
+val eval_callee : Cil_types.exp -> request -> Cil_types.kernel_function list result (* Ignores non-function values; exp must come from Cil Call constructor and are restricted to lvalues with no offset *)
+
 (* Value conversion *)
 val as_int : evaluation -> int result
 val as_integer : evaluation -> Integer.t result
 val as_float : evaluation -> float result
-val as_functions : evaluation -> Cil_types.kernel_function list result (* Ignores non-function values *)
 val as_ival : evaluation -> Ival.t result
 val as_fval : evaluation -> Fval.t result
 val as_cvalue : evaluation -> Cvalue.V.t result
-- 
GitLab