From cde12158a17c120e4d9d965a11f006c078fb12c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr> Date: Thu, 27 Feb 2020 13:33:12 +0100 Subject: [PATCH] [Eva] Abstract values: new function assume_pointer. --- src/plugins/value/values/abstract_value.mli | 9 ++++++ src/plugins/value/values/cvalue_forward.ml | 29 +++++++++++++++++++ src/plugins/value/values/cvalue_forward.mli | 1 + src/plugins/value/values/main_values.ml | 2 ++ .../value/values/numerors/numerors_value.ml | 1 + src/plugins/value/values/offsm_value.ml | 1 + src/plugins/value/values/sign_value.ml | 1 + src/plugins/value/values/value_product.ml | 5 ++++ 8 files changed, 49 insertions(+) diff --git a/src/plugins/value/values/abstract_value.mli b/src/plugins/value/values/abstract_value.mli index 378c06407ac..bd42be08f83 100644 --- a/src/plugins/value/values/abstract_value.mli +++ b/src/plugins/value/values/abstract_value.mli @@ -92,6 +92,15 @@ module type S = sig floating-point values. *) val assume_not_nan: assume_finite:bool -> fkind -> t -> t truth + (** Assumes that the abstract value only represents well-formed pointer values: + pointers either to an element of an array object or one past the last + element of an array object. (A pointer to an object that is not an element + of an array is viewed as a pointer to the first element of an array of + length one with the type of the object as its element type.) + The NULL pointer is always a valid pointer value. Function pointers are + also considered as valid pointer values for now. *) + val assume_pointer: t -> t truth + (* [assume_comparable cmp v1 v2] assumes that the integer or pointer values [v1] and [v2] are comparable for [cmp]. Integers are always comparable. If one value is a pointer, then both values should be pointers, and: diff --git a/src/plugins/value/values/cvalue_forward.ml b/src/plugins/value/values/cvalue_forward.ml index ad45ab9ddb8..6822e5f5a5c 100644 --- a/src/plugins/value/values/cvalue_forward.ml +++ b/src/plugins/value/values/cvalue_forward.ml @@ -220,6 +220,35 @@ let assume_not_nan ~assume_finite fkind v = let res = Bottom.non_bottom (backward_propagate kind res) in `Unknown (V.inject_float res) +let nearly_valid_bits = function + | Base.Empty + | Base.Invalid -> Integer.zero, Integer.zero + | Base.Known (min, max) | Base.Unknown (min, _, max) -> min, Integer.succ max + | Base.Variable variable -> Integer.zero, Integer.succ variable.Base.max_alloc + +let nearly_valid_offset base = + let min, max = nearly_valid_bits base in + let to_byte bound = Some (Integer.e_div bound (Bit_utils.sizeofchar ())) in + Ival.inject_range (to_byte min) (to_byte max) + +let assume_pointer loc = + let aux base ival (acc_v, acc_ok) = + let validity = Base.validity base in + let nearly_valid_ival = nearly_valid_offset validity in + let new_ival = Ival.narrow ival nearly_valid_ival in + let ival, ok = + if Base.is_null base && Ival.contains_zero ival + then Ival.(join zero new_ival), acc_ok && Ival.is_zero ival + else new_ival, acc_ok && Ival.equal ival new_ival + in + Locations.Location_Bytes.add base ival acc_v, ok + in + try + let loc, ok = Cvalue.V.(fold_topset_ok aux loc (bottom, true)) in + if Cvalue.V.is_bottom loc then `False + else if ok then `True else `Unknown loc + with Abstract_interp.Error_Top -> `Unknown loc + (* -------------------------------------------------------------------------- Integer overflow -------------------------------------------------------------------------- *) diff --git a/src/plugins/value/values/cvalue_forward.mli b/src/plugins/value/values/cvalue_forward.mli index 77b587c28e4..07fb2ef7591 100644 --- a/src/plugins/value/values/cvalue_forward.mli +++ b/src/plugins/value/values/cvalue_forward.mli @@ -31,6 +31,7 @@ val are_comparable: Abstract_interp.Comp.t -> V.t -> V.t -> bool val assume_non_zero: V.t -> V.t truth val assume_bounded: bound_kind -> bound -> V.t -> V.t truth val assume_not_nan: assume_finite:bool -> fkind -> V.t -> V.t truth +val assume_pointer: V.t -> V.t truth val assume_comparable: pointer_comparison -> V.t -> V.t -> (V.t * V.t) truth val forward_binop_int: typ: typ -> V.t -> binop -> V.t -> V.t diff --git a/src/plugins/value/values/main_values.ml b/src/plugins/value/values/main_values.ml index ebd8d3b0989..9218b0a03a3 100644 --- a/src/plugins/value/values/main_values.ml +++ b/src/plugins/value/values/main_values.ml @@ -46,6 +46,7 @@ module CVal = struct let assume_non_zero = Cvalue_forward.assume_non_zero let assume_bounded = Cvalue_forward.assume_bounded let assume_not_nan = Cvalue_forward.assume_not_nan + let assume_pointer = Cvalue_forward.assume_pointer let assume_comparable = Cvalue_forward.assume_comparable let constant exp = function @@ -165,6 +166,7 @@ module Interval = struct let assume_non_zero v = `Unknown v let assume_bounded _ _ v = `Unknown v let assume_not_nan ~assume_finite:_ _ v = `Unknown v + let assume_pointer v = `Unknown v let assume_comparable _ v1 v2 = `Unknown (v1, v2) let constant _ _ = top diff --git a/src/plugins/value/values/numerors/numerors_value.ml b/src/plugins/value/values/numerors/numerors_value.ml index da6a115444b..443a2dd4434 100644 --- a/src/plugins/value/values/numerors/numerors_value.ml +++ b/src/plugins/value/values/numerors/numerors_value.ml @@ -312,6 +312,7 @@ let backward_binop ~input_type:_ ~resulting_type:_ op ~left ~right ~result = let assume_non_zero v = `Unknown v let assume_bounded _kind _bound v = `Unknown v let assume_not_nan ~assume_finite:_ _fkind v = `Unknown v +let assume_pointer v = `Unknown v let assume_comparable _cmp v1 v2 = `Unknown (v1, v2) let rewrap_integer _ _ = top diff --git a/src/plugins/value/values/offsm_value.ml b/src/plugins/value/values/offsm_value.ml index 672025219b7..d6d7995ae35 100644 --- a/src/plugins/value/values/offsm_value.ml +++ b/src/plugins/value/values/offsm_value.ml @@ -423,6 +423,7 @@ module Offsm : Abstract_value.Leaf with type t = offsm_or_top = struct let assume_non_zero v = `Unknown v let assume_bounded _ _ v = `Unknown v let assume_not_nan ~assume_finite:_ _ v = `Unknown v + let assume_pointer v = `Unknown v let assume_comparable _ v1 v2 = `Unknown (v1, v2) let constant e _c = diff --git a/src/plugins/value/values/sign_value.ml b/src/plugins/value/values/sign_value.ml index 58f961a324d..74c45a2c268 100644 --- a/src/plugins/value/values/sign_value.ml +++ b/src/plugins/value/values/sign_value.ml @@ -120,6 +120,7 @@ let assume_non_zero v = let assume_bounded _ _ v = `Unknown v let assume_not_nan ~assume_finite:_ _ v = `Unknown v +let assume_pointer v = `Unknown v let assume_comparable _ v1 v2 = `Unknown (v1, v2) (** {2 Forward transfer functions} *) diff --git a/src/plugins/value/values/value_product.ml b/src/plugins/value/values/value_product.ml index 5b612953614..99d6ff34751 100644 --- a/src/plugins/value/values/value_product.ml +++ b/src/plugins/value/values/value_product.ml @@ -81,6 +81,11 @@ module Make and right_truth = Right.assume_not_nan ~assume_finite fkind right in narrow_truth (left, left_truth) (right, right_truth) + let assume_pointer (left, right) = + let left_truth = Left.assume_pointer left + and right_truth = Right.assume_pointer right in + narrow_truth (left, left_truth) (right, right_truth) + let assume_comparable op (l1, r1) (l2, r2) = let left_truth = Left.assume_comparable op l1 l2 and right_truth = Right.assume_comparable op r1 r2 in -- GitLab