Skip to content

Commit a857f75

Browse files
committed
Merge branch 'master' into unrolltype
2 parents 031001e + d4e2a5f commit a857f75

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2625
-606
lines changed

dune-project

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(lang dune 3.7)
1+
(lang dune 3.13)
22
(using dune_site 0.1)
33
(cram enable)
44
(name goblint)

goblint.opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ homepage: "https://goblint.in.tum.de"
3535
doc: "https://goblint.readthedocs.io/en/latest/"
3636
bug-reports: "https://github.com/goblint/analyzer/issues"
3737
depends: [
38-
"dune" {>= "3.7"}
38+
"dune" {>= "3.13"}
3939
"ocaml" {>= "4.14"}
4040
"goblint-cil" {>= "2.0.5"}
4141
"batteries" {>= "3.5.1"}

scripts/creduce/branches.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
gcc -c -Werror=implicit-function-declaration ./bad.c
6+
7+
GOBLINTDIR="/home/simmo/dev/goblint/sv-comp/goblint"
8+
OPTS="--conf $GOBLINTDIR/conf/svcomp.json --set ana.specification $GOBLINTDIR/../sv-benchmarks/c/properties/unreach-call.prp bad.c --enable pre.enabled"
9+
LOG="goblint.log"
10+
11+
$GOBLINTDIR/goblint $OPTS -v &> $LOG
12+
13+
grep -F "Both branches dead" $LOG

src/analyses/apron/affineEqualityAnalysis.apron.ml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,30 @@
44

55
open Analyses
66

7+
open SparseVector
8+
open ListMatrix
9+
10+
open ArrayVector
11+
open ArrayMatrix
12+
713
include RelationAnalysis
814

15+
(* There are two versions of the affeq domain.
16+
1. Sparse without side effects
17+
2. Dense Array with side effects
18+
Default: sparse implementation
19+
The array implementation with side effects of the affeq domain is used when the --disable ana.affeq.sparse option is set *)
20+
let get_domain: (module RelationDomain.RD) Lazy.t =
21+
lazy (
22+
if GobConfig.get_bool "ana.affeq.sparse" then
23+
(module AffineEqualityDomain.D2 (SparseVector) (ListMatrix))
24+
else
25+
(module AffineEqualityDenseDomain.D2 (ArrayVector) (ArrayMatrix))
26+
)
27+
928
let spec_module: (module MCPSpec) Lazy.t =
1029
lazy (
11-
let module AD = AffineEqualityDomain.D2 (VectorMatrix.ArrayVector) (VectorMatrix.ArrayMatrix) in
30+
let module AD = (val Lazy.force get_domain) in
1231
let module Priv = (val RelationPriv.get_priv ()) in
1332
let module Spec =
1433
struct

src/analyses/apron/relationAnalysis.apron.ml

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -465,17 +465,15 @@ struct
465465

466466
(* Give the set of reachables from argument. *)
467467
let reachables (ask: Queries.ask) es =
468-
let reachable e st =
469-
match st with
470-
| None -> None
471-
| Some st ->
468+
let reachable acc e =
469+
Option.bind acc (fun st ->
472470
let ad = ask.f (Queries.ReachableFrom e) in
473471
if Queries.AD.is_top ad then
474472
None
475473
else
476-
Some (Queries.AD.join ad st)
474+
Some (Queries.AD.join ad st))
477475
in
478-
List.fold_right reachable es (Some (Queries.AD.empty ()))
476+
List.fold_left reachable (Some (Queries.AD.empty ())) es
479477

480478

481479
let forget_reachable man st es =
@@ -484,9 +482,8 @@ struct
484482
match reachables ask es with
485483
| None ->
486484
(* top reachable, so try to invalidate everything *)
487-
RD.vars st.rel
488-
|> List.filter_map RV.to_cil_varinfo
489-
|> List.map Cil.var
485+
let to_cil_lval x = Option.map Cil.var @@ RV.to_cil_varinfo x in
486+
RD.vars st.rel |> List.filter_map to_cil_lval
490487
| Some ad ->
491488
let to_cil addr rs =
492489
match addr with
@@ -521,14 +518,10 @@ struct
521518
match desc.special args, f.vname with
522519
| Assert { exp; refine; _ }, _ -> assert_fn man exp refine
523520
| ThreadJoin { thread = id; ret_var = retvar }, _ ->
524-
(
525-
(* Forget value that thread return is assigned to *)
526-
let st' = forget_reachable man st [retvar] in
527-
let st' = Priv.thread_join ask man.global id st' in
528-
match r with
529-
| Some lv -> invalidate_one ask man st' lv
530-
| None -> st'
531-
)
521+
(* Forget value that thread return is assigned to *)
522+
let st' = forget_reachable man st [retvar] in
523+
let st' = Priv.thread_join ask man.global id st' in
524+
Option.map_default (invalidate_one ask man st') st' r
532525
| ThreadExit _, _ ->
533526
begin match ThreadId.get_current ask with
534527
| `Lifted tid ->
@@ -543,11 +536,10 @@ struct
543536
let id = List.hd args in
544537
Priv.thread_join ~force:true ask man.global id st
545538
| Rand, _ ->
546-
(match r with
547-
| Some lv ->
539+
Option.map_default (fun lv ->
548540
let st = invalidate_one ask man st lv in
549541
assert_fn {man with local = st} (BinOp (Ge, Lval lv, zero, intType)) true
550-
| None -> st)
542+
) st r
551543
| _, _ ->
552544
let lvallist e =
553545
match ask.f (Queries.MayPointTo e) with
@@ -575,10 +567,7 @@ struct
575567
let shallow_lvals = List.concat_map lvallist shallow_addrs in
576568
let st' = List.fold_left (invalidate_one ask man) st' shallow_lvals in
577569
(* invalidate lval if present *)
578-
match r with
579-
| Some lv -> invalidate_one ask man st' lv
580-
| None -> st'
581-
570+
Option.map_default (invalidate_one ask man st') st' r
582571

583572
let query_invariant man context =
584573
let keep_local = GobConfig.get_bool "ana.relation.invariant.local" in

src/analyses/base.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ struct
518518
(* From a list of values, presumably arguments to a function, simply extract
519519
* the pointer arguments. *)
520520
let get_ptrs (vals: value list): address list =
521-
let f (x:value) acc = match x with
521+
let f acc (x:value) = match x with
522522
| Address adrs when AD.is_top adrs ->
523523
M.info ~category:Unsound "Unknown address given as function argument"; acc
524524
| Address adrs when AD.to_var_may adrs = [] -> acc
@@ -528,7 +528,7 @@ struct
528528
| Top -> M.info ~category:Unsound "Unknown value type given as function argument"; acc
529529
| _ -> acc
530530
in
531-
List.fold_right f vals []
531+
List.fold_left f [] vals
532532

533533
let rec reachable_from_value ask (value: value) (t: typ) (description: string) =
534534
let empty = AD.empty () in
@@ -572,7 +572,7 @@ struct
572572
if M.tracing then M.traceli "reachability" "Checking reachable arguments from [%a]!" (d_list ", " AD.pretty) args;
573573
let empty = AD.empty () in
574574
(* We begin looking at the parameters: *)
575-
let argset = List.fold_right (AD.join) args empty in
575+
let argset = List.fold_left (AD.join) empty args in
576576
let workset = ref argset in
577577
(* And we keep a set of already visited variables *)
578578
let visited = ref empty in

src/analyses/baseInvariant.ml

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ struct
8585

8686
let refine_lv man st c x c' pretty exp =
8787
let set' lval v st = set st (eval_lv ~man st lval) (Cilfacade.typeOfLval lval) ~lval_raw:lval v ~man in
88+
let default () =
89+
(* For accesses via pointers in complicated case, no refinement yet *)
90+
let old_val = eval_rv_lval_refine ~man st exp x in
91+
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
92+
let v = apply_invariant ~old_val ~new_val:c' in
93+
if is_some_bot v then contra st
94+
else (
95+
if M.tracing then M.tracel "inv" "improve lval %a from %a to %a (c = %a, c' = %a)" d_lval x VD.pretty old_val VD.pretty v pretty c VD.pretty c';
96+
set' x v st
97+
)
98+
in
8899
match x with
89100
| Var var, o when refine_entire_var ->
90101
(* For variables, this is done at to the level of entire variables to benefit e.g. from disjunctive struct domains *)
@@ -100,17 +111,40 @@ struct
100111
if M.tracing then M.tracel "inv" "st from %a to %a" D.pretty st D.pretty r;
101112
r
102113
)
114+
| Mem (Lval lv), off ->
115+
(* Underlying lvals (may have offsets themselves), e.g., for struct members NOT including any offset appended to outer Mem *)
116+
let lvals = eval_lv ~man st (Mem (Lval lv), NoOffset) in
117+
(* Additional offset of value being refined in Addr Offset type *)
118+
let original_offset = convert_offset ~man st off in
119+
let res = AD.fold (fun base_a acc ->
120+
Option.bind acc (fun acc ->
121+
match base_a with
122+
| Addr _ ->
123+
let (lval_a:VD.t) = Address (AD.singleton base_a) in
124+
if M.tracing then M.tracel "inv" "Consider case of lval %a = %a" d_lval lv VD.pretty lval_a;
125+
let st = set' lv lval_a st in
126+
let orig = AD.Addr.add_offset base_a original_offset in
127+
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 *)
129+
(* this what I would originally have liked to do, but eval_rv_lval_refine uses queries and thus stale values *)
130+
(* let old_val = eval_rv_lval_refine ~man st exp x in *)
131+
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
132+
let v = apply_invariant ~old_val ~new_val:c' in
133+
if is_some_bot v then
134+
Some (D.join acc (try contra st with Analyses.Deadcode -> D.bot ()))
135+
else (
136+
if M.tracing then M.tracel "inv" "improve lval %a from %a to %a (c = %a, c' = %a)" d_lval x VD.pretty old_val VD.pretty v pretty c VD.pretty c';
137+
Some (D.join acc (set' x v st))
138+
)
139+
| _ -> None
140+
)
141+
) lvals (Some (D.bot ()))
142+
in
143+
BatOption.map_default_delayed (fun d -> if D.is_bot d then raise Analyses.Deadcode else d) default res
103144
| Var _, _
104145
| Mem _, _ ->
105-
(* For accesses via pointers, not yet *)
106-
let old_val = eval_rv_lval_refine ~man st exp x in
107-
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
108-
let v = apply_invariant ~old_val ~new_val:c' in
109-
if is_some_bot v then contra st
110-
else (
111-
if M.tracing then M.tracel "inv" "improve lval %a from %a to %a (c = %a, c' = %a)" d_lval x VD.pretty old_val VD.pretty v pretty c VD.pretty c';
112-
set' x v st
113-
)
146+
default ()
147+
114148

115149
let invariant_fallback man st exp tv =
116150
(* We use a recursive helper function so that x != 0 is false can be handled

src/analyses/malloc_null.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ struct
9494
(* Remove null values from state that are unreachable from exp.*)
9595
let remove_unreachable (ask: Queries.ask) (args: exp list) (st: D.t) : D.t =
9696
let reachable =
97-
let do_exp e a =
97+
let do_exp a e =
9898
match ask.f (Queries.ReachableFrom e) with
9999
| ad when not (Queries.AD.is_top ad) ->
100100
ad
@@ -103,9 +103,9 @@ struct
103103
| _ -> false)
104104
|> Queries.AD.join a
105105
(* Ignore soundness warnings, as invalidation proper will raise them. *)
106-
| _ -> AD.empty ()
106+
| _ -> a
107107
in
108-
List.fold_right do_exp args (AD.empty ())
108+
List.fold_left do_exp (AD.empty ()) args
109109
in
110110
let vars =
111111
reachable
@@ -164,7 +164,7 @@ struct
164164
let return_addr () = !return_addr_
165165

166166
let return man (exp:exp option) (f:fundec) : D.t =
167-
let remove_var x v = List.fold_right D.remove (to_addrs v) x in
167+
let remove_var x v = List.fold_left (Fun.flip D.remove) x (to_addrs v) in
168168
let nst = List.fold_left remove_var man.local (f.slocals @ f.sformals) in
169169
match exp with
170170
| Some ret ->

src/analyses/region.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ struct
5555
| Queries.Regions e ->
5656
let regpart = man.global () in
5757
if is_bullet e regpart man.local then Queries.Result.bot q (* TODO: remove bot *) else
58-
let ls = List.fold_right Queries.LS.add (regions e regpart man.local) (Queries.LS.empty ()) in
58+
let ls = List.fold_left (Fun.flip Queries.LS.add) (Queries.LS.empty ()) (regions e regpart man.local) in
5959
ls
6060
| _ -> Queries.Result.top q
6161

src/analyses/symbLocks.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ struct
4343
let assign man lval rval = invalidate_lval (Analyses.ask_of_man man) lval man.local
4444

4545
let return man exp fundec =
46-
List.fold_right D.remove_var (fundec.sformals@fundec.slocals) man.local
46+
let rm list acc = List.fold_left (Fun.flip D.remove_var) acc list in
47+
rm fundec.slocals (rm fundec.sformals man.local)
4748

4849
let enter man lval f args = [(man.local,man.local)]
4950
let combine_env man lval fexp f args fc au f_ask = au

0 commit comments

Comments
 (0)