Skip to content

Commit 44e9549

Browse files
Merge branch 'master' into issue_1328
2 parents 05dfb9f + 6d2654f commit 44e9549

30 files changed

+294
-68
lines changed

.github/workflows/docker.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
6060
- name: Build Docker image
6161
id: build
62-
uses: docker/build-push-action@v5
62+
uses: docker/build-push-action@v6
6363
with:
6464
context: .
6565
load: true # load into docker instead of immediately pushing
@@ -72,7 +72,7 @@ jobs:
7272
run: docker run --rm -v $(pwd):/data ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} /data/tests/regression/04-mutex/01-simple_rc.c # run image by version in case multiple tags
7373

7474
- name: Push Docker image
75-
uses: docker/build-push-action@v5
75+
uses: docker/build-push-action@v6
7676
with:
7777
context: .
7878
push: true

.github/workflows/unlocked.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ jobs:
165165

166166
- name: Build dev Docker image
167167
id: build
168-
uses: docker/build-push-action@v5
168+
uses: docker/build-push-action@v6
169169
with:
170170
context: .
171171
target: dev

.zenodo.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
"affiliation": "Technische Universität München",
2424
"orcid": "0009-0009-9644-7475"
2525
},
26+
{
27+
"name": "Holter, Karoliine",
28+
"affiliation": "University of Tartu",
29+
"orcid": "0009-0008-3725-4131"
30+
},
2631
{
2732
"name": "Vogler, Ralf",
2833
"affiliation": "Technische Universität München"

CITATION.cff

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ authors: # same authors as in .zenodo.json and dune-project
2121
family-names: Tilscher
2222
affiliation: "Technische Universität München"
2323
orcid: "https://orcid.org/0009-0009-9644-7475"
24+
- given-names: Karoliine
25+
family-names: Holter
26+
affiliation: "University of Tartu"
27+
orcid: "https://orcid.org/0009-0008-3725-4131"
2428
- given-names: Ralf
2529
family-names: Vogler
2630
affiliation: "Technische Universität München"

conf/examples/medium-program.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"base",
1010
"threadid",
1111
"threadflag",
12+
"threadreturn",
1213
"mallocWrapper",
1314
"mutexEvents",
1415
"mutex",
@@ -18,6 +19,7 @@
1819
"expRelation",
1920
"mhp",
2021
"assert",
22+
"pthreadMutexType",
2123
"var_eq",
2224
"symb_locks",
2325
"region",

conf/examples/very-precise.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"base",
2323
"threadid",
2424
"threadflag",
25+
"threadreturn",
2526
"mallocWrapper",
2627
"mutexEvents",
2728
"mutex",
@@ -31,6 +32,7 @@
3132
"expRelation",
3233
"mhp",
3334
"assert",
35+
"pthreadMutexType",
3436
"var_eq",
3537
"symb_locks",
3638
"region",

docs/user-guide/assumptions.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,22 @@ _NB! This list is likely incomplete._
1717

1818
See [PR #1414](https://github.com/goblint/analyzer/pull/1414).
1919

20+
2. Pointer arithmetic does not overflow.
21+
22+
[C11's N1570][n1570] at 6.5.6.8 states that
23+
24+
> When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand.
25+
> [...]
26+
> the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
27+
28+
after a long list of defined behaviors.
29+
30+
Goblint does not report overflow and out-of-bounds pointer arithmetic (when the pointer _is not dereferenced_).
31+
This affects the overflow analysis (SV-COMP no-overflow property) in the `base` analysis.
32+
33+
This _does not_ affect the `memOutOfBounds` analysis (SV-COMP valid-memsafety property), which is for undefined behavior from _dereferencing_ such out-of-bounds pointers.
34+
35+
See [PR #1511](https://github.com/goblint/analyzer/pull/1511).
36+
37+
38+
[n1570]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

dune-project

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,26 @@
1515
(source (github goblint/analyzer))
1616
(homepage "https://goblint.in.tum.de")
1717
(documentation "https://goblint.readthedocs.io/en/latest/")
18-
(authors "Simmo Saan" "Michael Schwarz" "Julian Erhard" "Sarah Tilscher" "Ralf Vogler" "Kalmer Apinis" "Vesal Vojdani" ) ; same authors as in .zenodo.json and CITATION.cff
18+
(authors "Simmo Saan" "Michael Schwarz" "Julian Erhard" "Sarah Tilscher" "Karoliine Holter" "Ralf Vogler" "Kalmer Apinis" "Vesal Vojdani" ) ; same authors as in .zenodo.json and CITATION.cff
1919
(maintainers "Simmo Saan <[email protected]>" "Michael Schwarz <[email protected]>" "Karoliine Holter")
2020
(license MIT)
2121

2222
(package
2323
(name goblint)
2424
(synopsis "Static analysis framework for C")
25+
(description "\
26+
Goblint is a sound static analysis framework for C programs using abstract interpretation.
27+
It specializes in thread-modular verification of multi-threaded programs, especially regarding data races.
28+
Goblint includes analyses for assertions, overflows, deadlocks, etc and can be extended with new analyses.
29+
")
30+
(tags (
31+
"program analysis"
32+
"program verification"
33+
"static analysis"
34+
"abstract interpretation"
35+
"C"
36+
"data race analysis"
37+
"concurrency"))
2538
(depends
2639
(ocaml (>= 4.14))
2740
(goblint-cil (>= 2.0.3)) ; TODO no way to define as pin-depends? Used goblint.opam.template to add it for now. https://github.com/ocaml/dune/issues/3231. Alternatively, removing this line and adding cil as a git submodule and `(vendored_dirs cil)` as ./dune also works. This way, no more need to reinstall the pinned cil opam package on changes. However, then cil is cleaned and has to be rebuild together with goblint.

goblint.opam

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# This file is generated by dune, edit dune-project instead
22
opam-version: "2.0"
33
synopsis: "Static analysis framework for C"
4+
description: """
5+
Goblint is a sound static analysis framework for C programs using abstract interpretation.
6+
It specializes in thread-modular verification of multi-threaded programs, especially regarding data races.
7+
Goblint includes analyses for assertions, overflows, deadlocks, etc and can be extended with new analyses.
8+
"""
49
maintainer: [
510
"Simmo Saan <[email protected]>"
611
"Michael Schwarz <[email protected]>"
@@ -11,11 +16,21 @@ authors: [
1116
"Michael Schwarz"
1217
"Julian Erhard"
1318
"Sarah Tilscher"
19+
"Karoliine Holter"
1420
"Ralf Vogler"
1521
"Kalmer Apinis"
1622
"Vesal Vojdani"
1723
]
1824
license: "MIT"
25+
tags: [
26+
"program analysis"
27+
"program verification"
28+
"static analysis"
29+
"abstract interpretation"
30+
"C"
31+
"data race analysis"
32+
"concurrency"
33+
]
1934
homepage: "https://goblint.in.tum.de"
2035
doc: "https://goblint.readthedocs.io/en/latest/"
2136
bug-reports: "https://github.com/goblint/analyzer/issues"

goblint.opam.locked

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ authors: [
1212
"Michael Schwarz"
1313
"Julian Erhard"
1414
"Sarah Tilscher"
15+
"Karoliine Holter"
1516
"Ralf Vogler"
1617
"Kalmer Apinis"
1718
"Vesal Vojdani"
@@ -142,3 +143,16 @@ pin-depends: [
142143
]
143144
]
144145
depexts: ["libgraph-easy-perl"] {os-distribution = "ubuntu" & with-test}
146+
description: """\
147+
Goblint is a sound static analysis framework for C programs using abstract interpretation.
148+
It specializes in thread-modular verification of multi-threaded programs, especially regarding data races.
149+
Goblint includes analyses for assertions, overflows, deadlocks, etc and can be extended with new analyses."""
150+
tags: [
151+
"program analysis"
152+
"program verification"
153+
"static analysis"
154+
"abstract interpretation"
155+
"C"
156+
"data race analysis"
157+
"concurrency"
158+
]

src/analyses/apron/relationAnalysis.apron.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ struct
756756

757757
let sync ctx reason =
758758
(* After the solver is finished, store the results (for later comparison) *)
759-
if !AnalysisState.postsolving then begin
759+
if !AnalysisState.postsolving && GobConfig.get_string "exp.relation.prec-dump" <> "" then begin
760760
let keep_local = GobConfig.get_bool "ana.relation.invariant.local" in
761761
let keep_global = GobConfig.get_bool "ana.relation.invariant.global" in
762762

src/analyses/base.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ struct
261261
(* adds n to the last offset *)
262262
let rec addToOffset n (t:typ option) = function
263263
| `Index (i, `NoOffset) ->
264+
(* Binary operations on pointer types should not generate warnings in SV-COMP *)
265+
GobRef.wrap AnalysisState.executing_speculative_computations true @@ fun () ->
264266
(* If we have arrived at the last Offset and it is an Index, we add our integer to it *)
265267
`Index(IdxDom.add i (iDtoIdx n), `NoOffset)
266268
| `Field (f, `NoOffset) ->

src/analyses/mutexTypeAnalysis.ml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@ struct
1212

1313
let name () = "pthreadMutexType"
1414

15-
(* Removing indexes here avoids complicated lookups and allows to have the LVals as vars here, at the price that different types of mutexes in arrays are not dinstinguished *)
16-
module O = Offset.Unit
17-
18-
module V = struct
19-
include Printable.Prod(CilType.Varinfo)(O) (* TODO: use Mval.Unit *)
15+
module V =
16+
struct
17+
(* Removing indexes here avoids complicated lookups and allows to have the LVals as vars here, at the price that different types of mutexes in arrays are not dinstinguished *)
18+
include Mval.Unit
2019
let is_write_only _ = false
2120
end
2221

2322
module G = MAttr
2423

24+
module O = Offset.Unit
25+
2526
(* transfer functions *)
2627
let assign ctx (lval:lval) (rval:exp) : D.t =
2728
match lval with

src/analyses/unassumeAnalysis.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ struct
8585

8686
let yaml = match Yaml_unix.of_file (Fpath.v (GobConfig.get_string "witness.yaml.unassume")) with
8787
| Ok yaml -> yaml
88-
| Error (`Msg m) -> failwith ("Yaml_unix.of_file: " ^ m)
88+
| Error (`Msg m) ->
89+
Logs.error "Yaml_unix.of_file: %s" m;
90+
Svcomp.errorwith "witness missing"
8991
in
9092
let yaml_entries = yaml |> GobYaml.list |> BatResult.get_ok in
9193

src/autoTune.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ let enableAnalyses anas =
186186
(*escape is also still enabled, because otherwise we get a warning*)
187187
(*does not consider dynamic calls!*)
188188

189-
let notNeccessaryThreadAnalyses = ["race"; "deadlock"; "maylocks"; "symb_locks"; "thread"; "threadid"; "threadJoins"; "threadreturn"; "mhp"; "region"]
189+
let notNeccessaryThreadAnalyses = ["race"; "deadlock"; "maylocks"; "symb_locks"; "thread"; "threadid"; "threadJoins"; "threadreturn"; "mhp"; "region"; "pthreadMutexType"]
190190
let reduceThreadAnalyses () =
191191
let isThreadCreate = function
192192
| LibraryDesc.ThreadCreate _ -> true

src/build-info/dune

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
(target configVersion.ml)
1616
(mode (promote (until-clean) (only configVersion.ml))) ; replace existing file in source tree, even if releasing (only overrides)
1717
(deps (universe)) ; do not cache, always regenerate
18-
(action (pipe-stdout (bash "git describe --all --long --dirty || echo \"n/a\"") (with-stdout-to %{target} (bash "xargs printf '(* Automatically regenerated, changes do not persist! *)\nlet version = \"%s\"'")))))
18+
(action (pipe-stdout (bash "git describe --all --long --dirty || echo \"n/a\"") (with-stdout-to %{target} (bash "xargs printf '(* Automatically regenerated, changes do not persist! *)\nlet version = Sys.opaque_identity \"%s\"'")))))
1919

2020
(rule
2121
(target configProfile.ml)
@@ -31,7 +31,7 @@
3131
(target configDatetime.ml)
3232
(mode (promote (until-clean) (only configDatetime.ml))) ; replace existing file in source tree, even if releasing (only overrides)
3333
(deps (universe)) ; do not cache, always regenerate
34-
(action (pipe-stdout (bash "date +\"%Y-%m-%dT%H:%M:%S\" || echo \"n/a\"") (with-stdout-to %{target} (bash "xargs printf '(* Automatically regenerated, changes do not persist! *)\nlet datetime = \"%s\"'")))))
34+
(action (pipe-stdout (bash "date +\"%Y-%m-%dT%H:%M:%S\" || echo \"n/a\"") (with-stdout-to %{target} (bash "xargs printf '(* Automatically regenerated, changes do not persist! *)\nlet datetime = Sys.opaque_identity \"%s\"'")))))
3535

3636
(env
3737
(_

src/cdomain/value/cdomains/offset.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ struct
213213
let bits_offset, _size = GoblintCil.bitsOffset (TComp (field.fcomp, [])) field_as_offset in
214214
let bits_offset = idx_of_int bits_offset in
215215
let remaining_offset = offset_to_index_offset ~typ:field.ftype o in
216-
Idx.add bits_offset remaining_offset
216+
GobRef.wrap AnalysisState.executing_speculative_computations true @@ fun () -> Idx.add bits_offset remaining_offset
217217
| `Index (x, o) ->
218218
let (item_typ, item_size_in_bits) =
219219
match Option.map unrollType typ with
@@ -223,9 +223,10 @@ struct
223223
| _ ->
224224
(None, Idx.top ())
225225
in
226-
let bits_offset = Idx.mul item_size_in_bits x in
226+
(* Binary operations on offsets should not generate overflow warnings in SV-COMP *)
227+
let bits_offset = GobRef.wrap AnalysisState.executing_speculative_computations true @@ fun () -> Idx.mul item_size_in_bits x in
227228
let remaining_offset = offset_to_index_offset ?typ:item_typ o in
228-
Idx.add bits_offset remaining_offset
229+
GobRef.wrap AnalysisState.executing_speculative_computations true @@ fun () -> Idx.add bits_offset remaining_offset
229230
in
230231
offset_to_index_offset ?typ offs
231232

src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ module EqualitiesConjunction = struct
158158
let (newref,offs,divi) = (get_rhs d head) in
159159
let (coeff,y) = BatOption.get newref in
160160
let (y,yrhs) = inverse head (coeff,y,offs,divi) in (* reassemble yrhs out of components *)
161-
let shifted_cluster = (List.fold (fun map i ->
161+
let shifted_cluster = (List.fold (fun map i ->
162162
let irhs = (get_rhs d i) in (* old entry is i = irhs *)
163163
Rhs.subst yrhs y irhs |> (* new entry for i is irhs [yrhs/y] *)
164164
set_rhs map i
@@ -222,7 +222,7 @@ module EqualitiesConjunction = struct
222222
| Some (coeff,j), ((Some (coeff1,h1), o1, divi1) as oldi)->
223223
(match get_rhs ts j with
224224
(* ts[x_j]=o2/d2 ========> ... *)
225-
| (None , o2, divi2) ->
225+
| (None , o2, divi2) ->
226226
let newxi = Rhs.subst (None,o2,divi2) j (Some (coeff,j),offs,divi) in
227227
let newxh1 = snd @@ inverse i (coeff1,h1,o1,divi1) in
228228
let newxh1 = Rhs.subst newxi i newxh1 in
@@ -251,7 +251,7 @@ module EqualitiesConjunction = struct
251251
else (* var_i = var_i, i.e. it may occur on the rhs of other equalities *)
252252
(* so now, we transform with the inverse of the transformer: *)
253253
let inv = snd (inverse i (coeff,j,offs,divi)) in
254-
IntMap.fold (fun k v acc ->
254+
IntMap.fold (fun k v acc ->
255255
match v with
256256
| (Some (c,x),o,d) when x=i-> set_rhs acc k (Rhs.subst inv i v)
257257
| _ -> acc
@@ -281,7 +281,7 @@ struct
281281
let multiply a b =
282282
(* if one of them is a constant, then multiply. Otherwise, the expression is not linear *)
283283
match a, b with
284-
| [(None,coeff, divi)], c
284+
| [(None,coeff, divi)], c
285285
| c, [(None,coeff, divi)] -> multiply_with_Q coeff divi c
286286
| _ -> raise NotLinearExpr
287287
in
@@ -314,7 +314,7 @@ struct
314314
| x -> Some(x)
315315

316316
(** convert and simplify (wrt. reference variables) a texpr into a tuple of a list of monomials (coeff,varidx,divi) and a (constant/divi) *)
317-
let simplified_monomials_from_texp (t: t) texp =
317+
let simplified_monomials_from_texp (t: t) texp =
318318
BatOption.bind (monomials_from_texp t texp)
319319
(fun monomiallist ->
320320
let d = Option.get t.d in
@@ -323,7 +323,7 @@ struct
323323
| None -> let gcdee = Z.gcd adiv divi in exprcache,(Z.(aconst*divi/gcdee + offs*adiv/gcdee),Z.lcm adiv divi)
324324
| Some (coeff,idx) -> let (somevar,someoffs,somedivi)=Rhs.subst (EConj.get_rhs d idx) idx (v,offs,divi) in (* normalize! *)
325325
let newcache = Option.map_default (fun (coef,ter) -> IMap.add ter Q.((IMap.find_default zero ter exprcache) + make coef somedivi) exprcache) exprcache somevar in
326-
let gcdee = Z.gcd adiv divi in
326+
let gcdee = Z.gcd adiv divi in
327327
(newcache,(Z.(aconst*divi/gcdee + offs*adiv/gcdee),Z.lcm adiv divi))
328328
in
329329
let (expr,constant) = List.fold_left accumulate_constants (IMap.empty,(Z.zero,Z.one)) monomiallist in (* abstract simplification of the guard wrt. reference variables *)
@@ -339,7 +339,7 @@ struct
339339
BatOption.bind (simplified_monomials_from_texp t texp )
340340
(fun (sum_of_terms, (constant,divisor)) ->
341341
(match sum_of_terms with
342-
| [] -> Some (None, constant,divisor)
342+
| [] -> Some (None, constant,divisor)
343343
| [(coeff,var,divi)] -> Some (Rhs.canonicalize (Some (Z.mul divisor coeff,var), Z.mul constant divi,Z.mul divisor divi))
344344
|_ -> None))
345345

@@ -447,7 +447,7 @@ struct
447447
let t1 = change_d t1 sup_env ~add:true ~del:false in
448448
let t2 = change_d t2 sup_env ~add:true ~del:false in
449449
match t1.d, t2.d with
450-
| Some d1', Some d2' ->
450+
| Some d1', Some d2' ->
451451
EConj.IntMap.fold (fun lhs rhs map -> meet_with_one_conj map lhs rhs) (snd d2') t1 (* even on sparse d2, this will chose the relevant conjs to meet with*)
452452
| _ -> {d = None; env = sup_env}
453453

@@ -489,7 +489,7 @@ struct
489489
- lhs itself
490490
- criteria A and B that characterize equivalence class, depending on the reference variable and the affine expression parameters wrt. each EConj
491491
- rhs1
492-
- rhs2
492+
- rhs2
493493
however, we have to account for the sparseity of EConj maps by manually patching holes with default values *)
494494
let joinfunction lhs rhs1 rhs2 =
495495
(
@@ -516,15 +516,15 @@ struct
516516
let varentry ci offi ch offh xh =
517517
let (coeff,off,d) = Q.(ci,(offi*ch)-(ci*offh),ch) in (* compute new rhs in Q *)
518518
let (coeff,off,d) = Z.(coeff.num*d.den*off.den,off.num*d.den*coeff.den,d. num*coeff.den*off.den) in (* convert that back into Z *)
519-
Rhs.canonicalize (Some(coeff,xh),off,d)
519+
Rhs.canonicalize (Some(coeff,xh),off,d)
520520
in
521521
(* ci1 = a*ch1+b /\ ci2 = a*ch2+b *)
522522
(* ===> a = (ci1-ci2)/(ch1-ch2) b = ci2-a*ch2 *)
523-
let constentry ci1 ci2 ch1 ch2 xh =
523+
let constentry ci1 ci2 ch1 ch2 xh =
524524
let a = Q.((ci1-ci2) / (ch1-ch2)) in
525525
let b = Q.(ci2 - a*ch2) in
526526
Rhs.canonicalize (Some (Z.(a.num*b.den),xh),Z.(b.num*a.den) ,Z.(a.den*b.den) ) in
527-
let iterate map l =
527+
let iterate map l =
528528
match l with
529529
| (_, _, _, rhs , rhs' ) :: t when Rhs.equal rhs rhs' -> List.fold (fun acc (x,_,_,rh,_) -> EConj.set_rhs acc x rh) map l
530530
| (h, _, _, ((Some (ch,_),oh,dh)), ((Some _,_,_) )) :: t -> List.fold (fun acc (i,_,_,(monom,oi,di),_) -> EConj.set_rhs acc i (varentry Q.(make (fst@@Option.get monom) di) Q.(make oi di) Q.(make ch dh) Q.(make oh dh) h)) map t

0 commit comments

Comments
 (0)