Skip to content

Commit 62747a8

Browse files
authored
Merge pull request #1939 from goblint/intdomain-equal_to
Use `ID.equal_to` instead of `ID.to_int` where possible
2 parents 8748522 + 5bbc187 commit 62747a8

File tree

6 files changed

+58
-45
lines changed

6 files changed

+58
-45
lines changed

.semgrep/intDomain.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
rules:
2+
- id: intDomain-to_int-equal
3+
pattern-either:
4+
- pattern: ID.to_int $X = Some $Y
5+
- pattern: $X |> ID.to_int = Some $Y # Fix doesn't add correct parentheses
6+
- pattern: GobOption.exists (Z.equal $Y) (ID.to_int $X)
7+
fix: ID.equal_to $Y $X = `Eq
8+
message: use dedicated and optimized function instead
9+
languages: [ocaml]
10+
severity: WARNING

src/analyses/base.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2542,7 +2542,7 @@ struct
25422542
let dest_a, dest_typ = addr_type_of_exp dest in
25432543
let value =
25442544
match eval_ch with
2545-
| Int i when ID.to_int i = Some Z.zero ->
2545+
| Int i when ID.equal_to Z.zero i = `Eq ->
25462546
VD.zero_init_value dest_typ
25472547
| _ ->
25482548
VD.top_value dest_typ
@@ -2712,7 +2712,7 @@ struct
27122712
let st' =
27132713
(* TODO: should invalidate shallowly? https://github.com/goblint/analyzer/pull/1224#discussion_r1405826773 *)
27142714
match eval_rv ~man st ret_var with
2715-
| Int n when GobOption.exists (Z.equal Z.zero) (ID.to_int n) -> st
2715+
| Int n when ID.equal_to Z.zero n = `Eq -> st
27162716
| Address ret_a ->
27172717
begin match eval_rv ~man st id with
27182718
| Thread a when ValueDomain.Threads.is_top a -> invalidate ~must:true ~man st [ret_var]
@@ -2759,7 +2759,7 @@ struct
27592759
let ik = Cilfacade.ptrdiff_ikind () in
27602760
let sizeval = eval_int ~man st size in
27612761
let countval = eval_int ~man st n in
2762-
if ID.to_int countval = Some Z.one then
2762+
if ID.equal_to Z.one countval = `Eq then
27632763
let blob_set = Option.map_default (fun heap_var -> [heap_var, TVoid [], VD.Blob (VD.bot (), sizeval, ZeroInit.calloc)]) [] heap_var in
27642764
set_many ~man st ((eval_lv ~man st lv, (Cilfacade.typeOfLval lv), Address addr):: blob_set)
27652765
else
@@ -2785,7 +2785,7 @@ struct
27852785
match p_rv with
27862786
| Address a -> a
27872787
(* TODO: don't we already have logic for this? *)
2788-
| Int i when ID.to_int i = Some Z.zero -> AD.null_ptr
2788+
| Int i when ID.equal_to Z.zero i = `Eq -> AD.null_ptr
27892789
| Int i -> AD.top_ptr
27902790
| _ -> AD.top_ptr (* TODO: why does this ever happen? *)
27912791
in

src/analyses/baseInvariant.ml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ struct
292292
(* ikind is the type of a for limiting ranges of the operands a, b. The only binops which can have different types for a, b are Shiftlt, Shiftrt (not handled below; don't use ikind to limit b there). *)
293293
let inv_bin_int (a, b) ikind c op =
294294
let warn_and_top_on_zero x =
295-
if GobOption.exists (Z.equal Z.zero) (ID.to_int x) then
295+
if ID.equal_to Z.zero x = `Eq then
296296
(M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Must Undefined Behavior: Second argument of div or mod is 0, continuing with top";
297297
Checks.error Checks.Category.DivisionByZero "Must Undefined Behavior: Second argument of div or mod is 0, continuing with top";
298298
ID.top_of ikind)
@@ -348,7 +348,8 @@ struct
348348
* If the upper bound of a is divisible by b, we can also meet with the result of a/b*b - c to get the precise [3,3].
349349
* If b is negative we have to look at the lower bound. *)
350350
let is_divisible bound =
351-
GobOption.exists (fun ba -> ID.rem (ID.of_int ikind ba) b |> ID.to_int = Some Z.zero) (bound a)
351+
(* TODO: could check divisibility directly, instead of via ID? *)
352+
GobOption.exists (fun ba -> ID.equal_to Z.zero (ID.rem (ID.of_int ikind ba) b) = `Eq) (bound a)
352353
in
353354
let max_pos = match ID.maximal b with None -> true | Some x -> Z.compare x Z.zero >= 0 in
354355
let min_neg = match ID.minimal b with None -> true | Some x -> Z.compare x Z.zero < 0 in
@@ -372,11 +373,11 @@ struct
372373
let callerFundec = Node.find_fundec man.node in
373374
let a = if PrecisionUtil.(is_congruence_active (int_precision_from_fundec_or_config callerFundec)) then
374375
let two = Z.of_int 2 in
375-
match ID.to_int b, ID.to_excl_list c with
376-
| Some b, Some ([v], _) when Z.equal b two ->
376+
match ID.to_excl_list c with
377+
| Some ([v], _) when ID.equal_to two b = `Eq ->
377378
let k = if Z.equal (Z.abs (Z.rem v two)) Z.zero then Z.one else Z.zero in
378-
ID.meet (ID.of_congruence ikind (k, b)) a
379-
| _, _ -> a
379+
ID.meet (ID.of_congruence ikind (k, two)) a
380+
| _ -> a
380381
else a
381382
in
382383
a, b
@@ -457,26 +458,25 @@ struct
457458
else
458459
a, b
459460
| BAnd ->
460-
(* we only attempt to refine a here *)
461-
let b_int = ID.to_int b in
461+
(* we only attempt to refine a here *) (* TODO: why? *)
462462
let a =
463-
match b_int with
464-
| Some x when Z.equal x Z.one ->
465-
(match ID.to_bool c with
466-
| Some true -> ID.meet a (ID.of_congruence ikind (Z.one, Z.of_int 2))
467-
| Some false -> ID.meet a (ID.of_congruence ikind (Z.zero, Z.of_int 2))
468-
| None -> a)
469-
| _ -> a
463+
if ID.equal_to Z.one b = `Eq then (
464+
match ID.to_bool c with
465+
| Some true -> ID.meet a (ID.of_congruence ikind (Z.one, Z.of_int 2))
466+
| Some false -> ID.meet a (ID.of_congruence ikind (Z.zero, Z.of_int 2))
467+
| None -> a
468+
)
469+
else (
470+
if M.tracing then M.tracel "inv" "Unhandled operator %a" d_binop op;
471+
a
472+
)
470473
in
471474
if PrecisionUtil.get_bitfield () then
472475
(* refinement based on the following idea: bit set to zero in c and set to one in b must be zero in a and bit set to one in c must be one in a too (analogously for b) *)
473476
let ((az, ao), (bz, bo)) = BitfieldDomain.Bitfield.refine_band (ID.to_bitfield ikind a) (ID.to_bitfield ikind b) (ID.to_bitfield ikind c) in
474477
ID.meet a (ID.of_bitfield ikind (az, ao)), ID.meet b (ID.of_bitfield ikind (bz, bo))
475-
else if b_int = None then
476-
(if M.tracing then M.tracel "inv" "Unhandled operator %a" d_binop op;
477-
(a, b)
478-
)
479-
else a, b
478+
else
479+
(a, b)
480480
| op ->
481481
if M.tracing then M.tracel "inv" "Unhandled operator %a" d_binop op;
482482
a, b

src/cdomain/value/cdomains/addressDomain.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,12 @@ struct
222222
let to_bool x = if is_null x then Some false else if is_not_null x then Some true else None
223223

224224
let of_int i =
225-
match ID.to_int i with
226-
| x when GobOption.exists BigIntOps.(equal (zero)) x -> null_ptr
227-
| x when GobOption.exists BigIntOps.(equal (one)) x -> not_null
228-
| _ -> match ID.to_excl_list i with
225+
if ID.equal_to Z.zero i = `Eq then
226+
null_ptr
227+
else if ID.equal_to Z.one i = `Eq then
228+
not_null
229+
else
230+
match ID.to_excl_list i with
229231
| Some (xs, _) when List.exists BigIntOps.(equal (zero)) xs -> not_null
230232
| _ -> top_ptr
231233

src/cdomain/value/cdomains/arrayDomain.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ struct
541541
let n = ask.eval_int e in
542542
VDQ.ID.to_int n
543543
in
544+
(* TODO: use ID.equal_to here, VDQ.ID doesn't have though *)
544545
let equals_zero e = GobOption.exists (Z.equal Z.zero) (exp_value e) in
545546
let equals_maxIndex e =
546547
GobOption.exists2 (fun l -> Z.equal (Z.pred l)) (Option.bind length Idx.to_int) (exp_value e)

src/cdomain/value/cdomains/valueDomain.ml

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -291,10 +291,12 @@ struct
291291

292292
type retnull = Null | NotNull | Maybe
293293
let is_null = function
294-
| Int n when GobOption.exists (Z.equal Z.zero) (ID.to_int n) -> Null
295294
| Int n ->
296-
let zero_ik = ID.of_int (ID.ikind n) Z.zero in
297-
if ID.to_bool (ID.ne n zero_ik) = Some true then NotNull else Maybe
295+
begin match ID.equal_to Z.zero n with
296+
| `Eq -> Null
297+
| `Neq -> NotNull
298+
| `Top -> Maybe
299+
end
298300
| _ -> Maybe
299301

300302
let get_ikind = function
@@ -520,7 +522,7 @@ struct
520522
(* cast to voidPtr are ignored TODO what happens if our value does not fit? *)
521523
| TPtr (t,_) ->
522524
Address (match v with
523-
| Int x when ID.to_int x = Some Z.zero -> AD.null_ptr
525+
| Int x when ID.equal_to Z.zero x = `Eq -> AD.null_ptr
524526
| Int x -> AD.top_ptr
525527
(* we ignore casts to void* (above)! TODO report UB! *)
526528
| Address x -> cast_addr t x
@@ -584,7 +586,7 @@ struct
584586
false
585587
| (Int x, Int y) -> ID.leq x y
586588
| (Float x, Float y) -> FD.leq x y
587-
| (Int x, Address y) when ID.to_int x = Some Z.zero && not (AD.is_not_null y) -> true
589+
| (Int x, Address y) when ID.equal_to Z.zero x = `Eq && not (AD.is_not_null y) -> true
588590
| (Int _, Address y) when AD.may_be_unknown y -> true
589591
| (Address _, Int y) when ID.is_top_of (Cilfacade.ptrdiff_ikind ()) y -> true
590592
| (Address x, Address y) -> AD.leq x y
@@ -611,10 +613,10 @@ struct
611613
| (Int x, Int y) -> (try Int (ID.join x y) with IntDomain.IncompatibleIKinds m -> Messages.warn ~category:Analyzer ~tags:[Category Imprecise] "%s" m; Top)
612614
| (Float x, Float y) -> Float (FD.join x y)
613615
| (Int x, Address y)
614-
| (Address y, Int x) -> Address (match ID.to_int x with
615-
| Some x when Z.equal x Z.zero -> AD.join AD.null_ptr y
616-
| Some x -> AD.(join y not_null)
617-
| None -> AD.join y AD.top_ptr)
616+
| (Address y, Int x) -> Address (match ID.equal_to Z.zero x with (* TODO: AD.of_int? *)
617+
| `Eq -> AD.join AD.null_ptr y
618+
| `Neq -> AD.(join y not_null)
619+
| `Top -> AD.join y AD.top_ptr)
618620
| (Address x, Address y) -> Address (AD.join x y)
619621
| (Struct x, Struct y) -> Struct (Structs.join x y)
620622
| (Union x, Union y) -> Union (Unions.join x y)
@@ -644,10 +646,10 @@ struct
644646
| (Float x, Float y) -> Float (FD.widen x y)
645647
(* TODO: symmetric widen, wtf? *)
646648
| (Int x, Address y)
647-
| (Address y, Int x) -> Address (match ID.to_int x with
648-
| Some x when Z.equal x Z.zero -> AD.widen AD.null_ptr (AD.join AD.null_ptr y)
649-
| Some x -> AD.(widen y (join y not_null))
650-
| None -> AD.widen y (AD.join y AD.top_ptr))
649+
| (Address y, Int x) -> Address (match ID.equal_to Z.zero x with (* TODO: AD.of_int? *)
650+
| `Eq -> AD.widen AD.null_ptr (AD.join AD.null_ptr y)
651+
| `Neq -> AD.(widen y (join y not_null))
652+
| `Top -> AD.widen y (AD.join y AD.top_ptr))
651653
| (Address x, Address y) -> Address (AD.widen x y)
652654
| (Struct x, Struct y) -> Struct (Structs.widen x y)
653655
| (Union x, Union y) -> Union (Unions.widen x y)
@@ -1008,12 +1010,9 @@ struct
10081010
match v with
10091011
| (Var var, Field (fld,_)) ->
10101012
let toptype = fld.fcomp in
1011-
let blob_size_opt = ID.to_int s in
10121013
not @@ ask.is_multiple var
10131014
&& not @@ Cil.isVoidType t (* Size of value is known *)
1014-
&& GobOption.exists (fun blob_size -> (* Size of blob is known *)
1015-
Z.equal blob_size (Z.of_int @@ Cilfacade.bytesSizeOf (TComp (toptype, [])))
1016-
) blob_size_opt
1015+
&& ID.equal_to (Z.of_int @@ Cilfacade.bytesSizeOf (TComp (toptype, []))) s = `Eq (* Size of blob is known *)
10171016
| _ -> false
10181017
in
10191018
if do_strong_update then
@@ -1034,6 +1033,7 @@ struct
10341033
| (Var var, _) ->
10351034
let blob_size_opt = ID.to_int s in
10361035
not @@ ask.is_multiple var
1036+
(* TODO: could use ID.equal_to, but only if blob_destructive doesn't actually need known (but ignored!) size *)
10371037
&& GobOption.exists (fun blob_size -> (* Size of blob is known *)
10381038
(not @@ Cil.isVoidType t (* Size of value is known *)
10391039
&& Z.equal blob_size (Z.of_int @@ Cil.alignOf_int t))

0 commit comments

Comments
 (0)