Skip to content

Commit 9724fee

Browse files
authored
Merge pull request #1896 from goblint/overflow-cast-kind
Add cast kinds to integer overflow messages
2 parents c4c20df + af947ed commit 9724fee

File tree

17 files changed

+107
-100
lines changed

17 files changed

+107
-100
lines changed

src/analyses/base.ml

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct
167167
* Abstract evaluation functions
168168
**************************************************************************)
169169

170-
let iDtoIdx x = ID.cast_to (Cilfacade.ptrdiff_ikind ()) x
170+
let iDtoIdx x = ID.cast_to ~kind:Internal (Cilfacade.ptrdiff_ikind ()) x (* TODO: proper castkind *)
171171

172172
let unop_ID = function
173173
| Neg -> ID.neg
@@ -182,7 +182,7 @@ struct
182182

183183
(* Evaluating Cil's unary operators. *)
184184
let evalunop op typ: value -> value = function
185-
| Int v1 -> Int (ID.cast_to (Cilfacade.get_ikind typ) (unop_ID op v1))
185+
| Int v1 -> Int (ID.cast_to ~kind:Internal (Cilfacade.get_ikind typ) (unop_ID op v1)) (* TODO: proper castkind *)
186186
| Float v -> unop_FD op v
187187
| Address a when op = LNot ->
188188
if AD.is_null a then
@@ -332,7 +332,7 @@ struct
332332
(* Pointer subtracted by a value (e-i) is very similar *)
333333
(* Cast n to the (signed) ptrdiff_ikind, then add the its negated value. *)
334334
| MinusPI ->
335-
let n = ID.neg (ID.cast_to (Cilfacade.ptrdiff_ikind ()) n) in
335+
let n = ID.neg (ID.cast_to ~kind:Internal (Cilfacade.ptrdiff_ikind ()) n) in (* TODO: proper castkind *)
336336
Address (ad_concat_map (addToAddr n) p)
337337
| Mod -> Int (ID.top_of (Cilfacade.ptrdiff_ikind ())) (* we assume that address is actually casted to int first*)
338338
| _ -> Address AD.top_ptr
@@ -342,11 +342,11 @@ struct
342342
(* For the integer values, we apply the int domain operator *)
343343
| Int v1, Int v2 ->
344344
let result_ik = Cilfacade.get_ikind t in
345-
Int (ID.cast_to result_ik (binop_ID result_ik op v1 v2))
345+
Int (ID.cast_to ~kind:Internal result_ik (binop_ID result_ik op v1 v2)) (* TODO: proper castkind *)
346346
(* For the float values, we apply the float domain operators *)
347347
| Float v1, Float v2 when is_int_returning_binop_FD op ->
348348
let result_ik = Cilfacade.get_ikind t in
349-
Int (ID.cast_to result_ik (int_returning_binop_FD op v1 v2))
349+
Int (ID.cast_to ~kind:Internal result_ik (int_returning_binop_FD op v1 v2)) (* TODO: proper castkind *)
350350
| Float v1, Float v2 -> Float (binop_FD (Cilfacade.get_fkind t) op v1 v2)
351351
(* For address +/- value, we try to do some elementary ptr arithmetic *)
352352
| Address p, Int n
@@ -528,7 +528,7 @@ struct
528528
| Int _ ->
529529
let at = AD.type_of addrs in
530530
if Cil.isArithmeticType at then
531-
VD.cast at x
531+
VD.cast ~kind:Internal at x (* TODO: proper castkind *)
532532
else
533533
x
534534
| _ -> x
@@ -928,12 +928,12 @@ struct
928928
let array_start = add_offset_varinfo array_ofs in
929929
Address (AD.map array_start (eval_lv ~man st lval))
930930
| CastE (_, t, Const (CStr (x,e))) -> (* VD.top () *) eval_rv ~man st (Const (CStr (x,e))) (* TODO safe? *)
931-
| CastE (_, t, exp) ->
931+
| CastE (kind, t, exp) ->
932932
(let v = eval_rv ~man st exp in
933933
try
934-
VD.cast ~torg:(Cilfacade.typeOf exp) t v
934+
VD.cast ~kind ~torg:(Cilfacade.typeOf exp) t v
935935
with Cilfacade.TypeOfError _ ->
936-
VD.cast t v)
936+
VD.cast ~kind t v)
937937
| SizeOf _
938938
| Real _
939939
| Imag _
@@ -999,7 +999,7 @@ struct
999999
else
10001000
VD.top () (* upcasts not! *)
10011001
in
1002-
let v' = VD.cast t v in (* cast to the expected type (the abstract type might be something other than t since we don't change addresses upon casts!) *)
1002+
let v' = VD.cast ~kind:Internal t v in (* cast to the expected type (the abstract type might be something other than t since we don't change addresses upon casts!) *) (* TODO: proper castkind *)
10031003
if M.tracing then M.tracel "cast" "Ptr-Deref: cast %a to %a = %a!" VD.pretty v d_type t VD.pretty v';
10041004
let v' = VD.eval_offset (Queries.to_value_domain_ask (Analyses.ask_of_man man)) (fun x -> get ~man st x (Some exp)) v' (convert_offset ~man st ofs) (Some exp) None t in (* handle offset *)
10051005
v'
@@ -2061,7 +2061,7 @@ struct
20612061
if not (ThreadIdDomain.Thread.is_main tid) then ( (* Only non-main return constitutes an implicit pthread_exit according to man page (https://github.com/goblint/analyzer/issues/1767#issuecomment-3642590227). *)
20622062
(* Evaluate exp and cast the resulting value to the void-pointer-type.
20632063
Casting to the right type here avoids precision loss on joins. *)
2064-
let rv = VD.cast ~torg:(Cilfacade.typeOf exp) Cil.voidPtrType rv in
2064+
let rv = VD.cast ~kind:Internal ~torg:(Cilfacade.typeOf exp) Cil.voidPtrType rv in (* TODO: proper castkind *)
20652065
man.sideg (V.thread tid) (G.create_thread rv)
20662066
);
20672067
Priv.thread_return ask (priv_getg man.global) (priv_sideg man.sideg) tid st'
@@ -2324,7 +2324,7 @@ struct
23242324
let item_typ_size_in_bytes = size_of_type_in_bytes item_typ in
23252325
begin match man.ask (Queries.EvalLength ptr) with
23262326
| `Lifted arr_len ->
2327-
let arr_len_casted = ID.cast_to (Cilfacade.ptrdiff_ikind ()) arr_len in
2327+
let arr_len_casted = ID.cast_to ~kind:Internal (Cilfacade.ptrdiff_ikind ()) arr_len in (* TODO: proper castkind *)
23282328
begin
23292329
try `Lifted (ID.mul item_typ_size_in_bytes arr_len_casted)
23302330
with IntDomain.ArithmeticOnIntegerBot _ -> `Bot
@@ -2375,8 +2375,8 @@ struct
23752375
let dest_size_equal_n =
23762376
match dest_size, n_intdom with
23772377
| `Lifted ds, `Lifted n ->
2378-
let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in
2379-
let casted_n = ID.cast_to (Cilfacade.ptrdiff_ikind ()) n in
2378+
let casted_ds = ID.cast_to ~kind:Internal (Cilfacade.ptrdiff_ikind ()) ds in (* TODO: proper castkind *)
2379+
let casted_n = ID.cast_to ~kind:Internal (Cilfacade.ptrdiff_ikind ()) n in (* TODO: proper castkind *)
23802380
let ds_eq_n =
23812381
begin try ID.eq casted_ds casted_n
23822382
with IntDomain.ArithmeticOnIntegerBot _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind ()
@@ -2469,7 +2469,7 @@ struct
24692469
let ptrdiff_ik = Cilfacade.ptrdiff_ikind () in
24702470
let size = man.ask (Q.BlobSize {exp = s1; base_address = false}) in
24712471
let s_id =
2472-
try ValueDomainQueries.ID.unlift (ID.cast_to ptrdiff_ik) size
2472+
try ValueDomainQueries.ID.unlift (ID.cast_to ~kind:Internal ptrdiff_ik) size (* TODO: proper castkind *)
24732473
with Failure _ -> ID.top_of ptrdiff_ik in
24742474
let empty_array = CArrays.make s_id (Int (ID.top_of IChar)) in
24752475
set ~man st lv_a lv_typ (op_array empty_array array_s2)
@@ -2478,7 +2478,7 @@ struct
24782478
let ptrdiff_ik = Cilfacade.ptrdiff_ikind () in
24792479
let size = man.ask (Q.BlobSize {exp = s1; base_address = false}) in
24802480
let s_id =
2481-
try ValueDomainQueries.ID.unlift (ID.cast_to ptrdiff_ik) size
2481+
try ValueDomainQueries.ID.unlift (ID.cast_to ~kind:Internal ptrdiff_ik) size (* TODO: proper castkind *)
24822482
with Failure _ -> ID.top_of ptrdiff_ik in
24832483
let empty_array = CArrays.make s_id (Int (ID.top_of IChar)) in
24842484
let s2_null_bytes = List.map CArrays.to_null_byte_domain (AD.to_string s2_a) in
@@ -2642,7 +2642,7 @@ struct
26422642
let eval_x = eval_rv ~man st x in
26432643
begin match eval_x with
26442644
| Int int_x ->
2645-
let xcast = ID.cast_to ik int_x in
2645+
let xcast = ID.cast_to ~kind:Internal ik int_x in (* TODO: proper castkind *)
26462646
(* the absolute value of the most-negative value is out of range for 2'complement types *)
26472647
(match (ID.minimal xcast), (ID.minimal (ID.top_of ik)) with
26482648
| _, None
@@ -2661,11 +2661,11 @@ struct
26612661
| Nan (fk, str) when Cil.isPointerType (Cilfacade.typeOf str) -> Float (FD.nan_of fk)
26622662
| Nan _ -> failwith ("non-pointer argument in call to function "^f.vname)
26632663
| Inf fk -> Float (FD.inf_of fk)
2664-
| Isfinite x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isfinite x))
2665-
| Isinf x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isinf x))
2666-
| Isnan x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnan x))
2667-
| Isnormal x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnormal x))
2668-
| Signbit x -> Int (ID.cast_to IInt (apply_unary FDouble FD.signbit x))
2664+
| Isfinite x -> Int (ID.cast_to ~kind:Internal IInt (apply_unary FDouble FD.isfinite x)) (* TODO: proper castkind *)
2665+
| Isinf x -> Int (ID.cast_to ~kind:Internal IInt (apply_unary FDouble FD.isinf x)) (* TODO: proper castkind *)
2666+
| Isnan x -> Int (ID.cast_to ~kind:Internal IInt (apply_unary FDouble FD.isnan x)) (* TODO: proper castkind *)
2667+
| Isnormal x -> Int (ID.cast_to ~kind:Internal IInt (apply_unary FDouble FD.isnormal x)) (* TODO: proper castkind *)
2668+
| Signbit x -> Int (ID.cast_to ~kind:Internal IInt (apply_unary FDouble FD.signbit x)) (* TODO: proper castkind *)
26692669
| Ceil (fk,x) -> Float (apply_unary fk FD.ceil x)
26702670
| Floor (fk,x) -> Float (apply_unary fk FD.floor x)
26712671
| Fabs (fk, x) -> Float (apply_unary fk FD.fabs x)
@@ -2676,16 +2676,16 @@ struct
26762676
| Cos (fk, x) -> Float (apply_unary fk FD.cos x)
26772677
| Sin (fk, x) -> Float (apply_unary fk FD.sin x)
26782678
| Tan (fk, x) -> Float (apply_unary fk FD.tan x)
2679-
| Isgreater (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.gt x y))
2680-
| Isgreaterequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.ge x y))
2681-
| Isless (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.lt x y))
2682-
| Islessequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.le x y))
2683-
| Islessgreater (x,y) -> Int(ID.c_logor (ID.cast_to IInt (apply_binary FDouble FD.lt x y)) (ID.cast_to IInt (apply_binary FDouble FD.gt x y)))
2684-
| Isunordered (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.unordered x y))
2679+
| Isgreater (x,y) -> Int(ID.cast_to ~kind:Internal IInt (apply_binary FDouble FD.gt x y)) (* TODO: proper castkind *)
2680+
| Isgreaterequal (x,y) -> Int(ID.cast_to ~kind:Internal IInt (apply_binary FDouble FD.ge x y)) (* TODO: proper castkind *)
2681+
| Isless (x,y) -> Int(ID.cast_to ~kind:Internal IInt (apply_binary FDouble FD.lt x y)) (* TODO: proper castkind *)
2682+
| Islessequal (x,y) -> Int(ID.cast_to ~kind:Internal IInt (apply_binary FDouble FD.le x y)) (* TODO: proper castkind *)
2683+
| Islessgreater (x,y) -> Int(ID.c_logor (ID.cast_to ~kind:Internal IInt (apply_binary FDouble FD.lt x y)) (ID.cast_to ~kind:Internal IInt (apply_binary FDouble FD.gt x y))) (* TODO: proper castkind *)
2684+
| Isunordered (x,y) -> Int(ID.cast_to ~kind:Internal IInt (apply_binary FDouble FD.unordered x y)) (* TODO: proper castkind *)
26852685
| Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y)
26862686
| Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y)
26872687
| Sqrt (fk, x) -> Float (apply_unary fk FD.sqrt x)
2688-
| Abs (ik, x) -> Int (ID.cast_to ik (apply_abs ik x))
2688+
| Abs (ik, x) -> Int (ID.cast_to ~kind:Internal ik (apply_abs ik x)) (* TODO: proper castkind *)
26892689
end
26902690
in
26912691
Option.map_default (fun lv -> set ~man st (eval_lv ~man st lv) (Cilfacade.typeOfLval lv) result) st lv
@@ -2748,7 +2748,7 @@ struct
27482748
let blob_set = Option.map_default (fun heap_var -> [heap_var, TVoid [], VD.Blob (VD.bot (), sizeval, ZeroInit.calloc)]) [] heap_var in
27492749
set_many ~man st ((eval_lv ~man st lv, (Cilfacade.typeOfLval lv), Address addr):: blob_set)
27502750
else
2751-
let blobsize = ID.mul (ID.cast_to ik @@ sizeval) (ID.cast_to ik @@ countval) in
2751+
let blobsize = ID.mul (ID.cast_to ~kind:Internal ik @@ sizeval) (ID.cast_to ~kind:Internal ik @@ countval) in (* TODO: proper castkind *)
27522752
let offset = `Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) Z.zero, `NoOffset) in
27532753
(* the heap_var is the base address of the allocated memory, but we need to keep track of the offset for the blob *)
27542754
let addr_offset = AD.map (fun a -> Addr.add_offset a offset) addr in

src/analyses/baseInvariant.ml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ struct
125125
let st = set' lv lval_a st in
126126
let orig = AD.Addr.add_offset base_a original_offset in
127127
let old_val = get ~man st (AD.singleton orig) None in
128-
let old_val = VD.cast (Cilfacade.typeOfLval x) old_val in (* needed as the type of this pointer may be different *)
128+
let old_val = VD.cast ~kind:Internal (Cilfacade.typeOfLval x) old_val in (* needed as the type of this pointer may be different *) (* TODO: proper castkind *)
129129
(* this what I would originally have liked to do, but eval_rv_lval_refine uses queries and thus stale values *)
130130
(* let old_val = eval_rv_lval_refine ~man st exp x in *)
131131
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
@@ -157,7 +157,7 @@ struct
157157
(match value with
158158
| Int n ->
159159
let ikind = Cilfacade.get_ikind_exp (Lval lval) in
160-
`Refine (x, Int (ID.cast_to ikind n))
160+
`Refine (x, Int (ID.cast_to ~kind:Internal ikind n)) (* TODO: proper castkind *)
161161
| _ -> `Refine (x, value))
162162
(* The false-branch for x == value: *)
163163
| Eq, x, value, false -> begin
@@ -194,7 +194,7 @@ struct
194194
match value with
195195
| Int n -> begin
196196
let ikind = Cilfacade.get_ikind_exp (Lval lval) in
197-
let n = ID.cast_to ikind n in
197+
let n = ID.cast_to ~kind:Internal ikind n in (* TODO: proper castkind *)
198198
let range_from x = if tv then ID.ending ikind (Z.pred x) else ID.starting ikind x in
199199
let limit_from = if tv then ID.maximal else ID.minimal in
200200
match limit_from n with
@@ -209,7 +209,7 @@ struct
209209
match value with
210210
| Int n -> begin
211211
let ikind = Cilfacade.get_ikind_exp (Lval lval) in
212-
let n = ID.cast_to ikind n in
212+
let n = ID.cast_to ~kind:Internal ikind n in (* TODO: proper castkind *)
213213
let range_from x = if tv then ID.ending ikind x else ID.starting ikind (Z.succ x) in
214214
let limit_from = if tv then ID.maximal else ID.minimal in
215215
match limit_from n with
@@ -241,7 +241,7 @@ struct
241241
let v = eval_rv ~man st rval in
242242
let x_type = Cilfacade.typeOfLval x in
243243
if VD.is_dynamically_safe_cast x_type (Cilfacade.typeOf rval) v then
244-
helper op x (VD.cast x_type v) tv
244+
helper op x (VD.cast ~kind:Internal x_type v) tv (* TODO: proper castkind *)
245245
else
246246
`NotUnderstood
247247
| BinOp(op, rval, Lval x, typ) -> derived_invariant (BinOp(switchedOp op, Lval x, rval, typ)) tv
@@ -759,7 +759,7 @@ struct
759759
| a1, a2 -> fallback (fun () -> Pretty.dprintf "binop: got abstract values that are not Int: %a and %a" VD.pretty a1 VD.pretty a2) st)
760760
(* use closures to avoid unused casts *)
761761
in (match c_typed with
762-
| Int c -> invert_binary_op c ID.pretty (fun ik -> ID.cast_to ik c) (fun fk -> FD.of_int fk c)
762+
| Int c -> invert_binary_op c ID.pretty (fun ik -> ID.cast_to ~kind:Internal ik c) (fun fk -> FD.of_int fk c) (* TODO: proper castkind *)
763763
| Float c -> invert_binary_op c FD.pretty (fun ik -> FD.to_int ik c) (fun fk -> FD.cast_to fk c)
764764
| _ -> failwith "unreachable")
765765
| Lval x, (Int _ | Float _ | Address _) -> (* meet x with c *)
@@ -771,7 +771,7 @@ struct
771771
let c' = match t with
772772
| TPtr _ -> VD.Address (AD.of_int c)
773773
| TInt (ik, _)
774-
| TEnum ({ekind = ik; _}, _) -> Int (ID.cast_to ik c)
774+
| TEnum ({ekind = ik; _}, _) -> Int (ID.cast_to ~kind:Internal ik c) (* TODO: proper castkind *)
775775
| TFloat (fk, _) -> Float (FD.of_int fk c)
776776
| _ -> Int c
777777
in
@@ -783,7 +783,7 @@ struct
783783
if M.tracing then M.trace "invSpecial" "qry Result: %a" Queries.ML.pretty tmpSpecial;
784784
begin match tmpSpecial with
785785
| `Lifted (Abs (ik, xInt)) ->
786-
let c' = ID.cast_to ik c in (* different ik! *)
786+
let c' = ID.cast_to ~kind:Internal ik c in (* different ik! *) (* TODO: proper castkind *)
787787
inv_exp (Int (ID.join c' (ID.neg c'))) xInt st
788788
| tmpSpecial ->
789789
BatOption.map_default_delayed (fun tv ->
@@ -856,8 +856,8 @@ struct
856856
if VD.is_dynamically_safe_cast t t' (Int i) then
857857
(* let c' = ID.cast_to ik_e c in *)
858858
(* Suppressing overflow warnings as this is not a computation that comes from the program *)
859-
let res_range = (ID.cast_to ~suppress_ovwarn:true ik (ID.top_of ik_e)) in
860-
let c' = ID.cast_to ik_e (ID.meet c res_range) in (* TODO: cast without overflow, is this right for normal invariant? *)
859+
let res_range = (ID.cast_to ~suppress_ovwarn:true ~kind:Internal ik (ID.top_of ik_e)) in (* TODO: proper castkind *)
860+
let c' = ID.cast_to ~kind:Internal ik_e (ID.meet c res_range) in (* TODO: cast without overflow, is this right for normal invariant? *) (* TODO: proper castkind *)
861861
if M.tracing then M.tracel "inv" "cast: %a from %a to %a: i = %a; cast c = %a to %a = %a" d_exp e d_ikind ik_e d_ikind ik ID.pretty i ID.pretty c d_ikind ik_e ID.pretty c';
862862
inv_exp (Int c') e st
863863
else

0 commit comments

Comments
 (0)