Skip to content

Commit

Permalink
Merge branch 'master' into queries-ad
Browse files Browse the repository at this point in the history
  • Loading branch information
sim642 committed Sep 11, 2023
2 parents 3e01426 + 1128aba commit bb8a926
Show file tree
Hide file tree
Showing 39 changed files with 297 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up OCaml ${{ matrix.ocaml-compiler }}
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 # needed for GitHub Actions Cache in build-push-action
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Check for undocumented modules
run: python scripts/goblint-lib-modules.py
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/indentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/locked.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up OCaml ${{ matrix.ocaml-compiler }}
env:
Expand Down Expand Up @@ -101,7 +101,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up OCaml ${{ matrix.ocaml-compiler }}
env:
Expand Down Expand Up @@ -141,7 +141,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up OCaml ${{ matrix.ocaml-compiler }}
env:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/metadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Validate CITATION.cff
uses: docker://citationcff/cffconvert:latest
Expand All @@ -36,7 +36,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/semgrep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Run semgrep
run: semgrep scan --sarif --output=semgrep.sarif
run: semgrep scan --config .semgrep/ --sarif > semgrep.sarif

- name: Upload SARIF file to GitHub Advanced Security Dashboard
uses: github/codeql-action/upload-sarif@v2
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/unlocked.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v2
Expand Down Expand Up @@ -131,7 +131,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v2
Expand Down Expand Up @@ -208,7 +208,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 # needed for GitHub Actions Cache in build-push-action
Expand Down Expand Up @@ -246,7 +246,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v2
Expand Down
1 change: 1 addition & 0 deletions .semgrep/tracing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ rules:
- pattern: Messages.traceu
- pattern: Messages.traceli
- pattern-not-inside: if Messages.tracing then ...
- pattern-not-inside: if Messages.tracing && ... then ...
message: trace functions should only be called if tracing is enabled at compile time
languages: [ocaml]
severity: WARNING
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
## v2.2.0
* TODO OCaml 5 (#1003, #1137).
* TODO Library #1138
* TODO refactor race #1136

* Add `setjmp`/`longjmp` analysis (#887, #970, #1015, #1019).
* Refactor race analysis to lazy distribution (#1084, #1089, #1016).
* Add thread-unsafe library function call analysis (#723, #1082).
* Add mutex type analysis and mutex API analysis (#800, #839, #1073).
* Add interval set domain and string literals domain (#901, #966, #994, #1048).
* Add affine equalities analysis (#592).
* Add use-after-free analysis (#1050, #1114).
* Add dead code elimination transformation (#850, #979).
* Add taint analysis for partial contexts (#553, #952).
* Add YAML witness validation via unassume (#796, #977, #1044, #1045, #1124).
* Add incremental analysis rename detection (#774, #777).
* Fix address sets unsoundness (#822, #967, #564, #1032, #998, #1031).
* Fix thread escape analysis unsoundness (#939, #984, #1074, #1078).
* Fix many incremental analysis issues (#627, #836, #835, #841, #932, #678, #942, #949, #950, #957, #955, #954, #960, #959, #1004, #558, #1010, #1091).
* Fix server mode for abstract debugging (#983, #990, #997, #1000, #1001, #1013, #1018, #1017, #1026, #1027).
* Add documentation for configuration JSON schema and OCaml API (#999, #1054, #1055, #1053).
* Add many library function specifications (#962, #996, #1028, #1079, #1121, #1135).
* Add OCaml 5.0 support (#945).

## v2.1.0
Functionally equivalent to Goblint in SV-COMP 2023.

Expand Down
8 changes: 0 additions & 8 deletions conf/bench-yaml-validate.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,6 @@
"tokens": true
}
},
"witness": {
"enabled": false,
"invariant": {
"loop-head": true,
"after-lock": true,
"other": false
}
},
"sem": {
"unknown_function": {
"invalidate": {
Expand Down
14 changes: 0 additions & 14 deletions conf/bench-yaml.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@
]
}
},
"witness": {
"enabled": false,
"yaml": {
"enabled": true
},
"invariant": {
"exact": false,
"exclude-vars": [
"tmp\\(___[0-9]+\\)?",
"cond",
"RETURN"
]
}
},
"sem": {
"unknown_function": {
"invalidate": {
Expand Down
13 changes: 5 additions & 8 deletions conf/svcomp-yaml-validate.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"float": {
"interval": true
},
"apron": {
"domain": "polyhedra",
"strengthening": true
},
"activated": [
"base",
"threadid",
Expand All @@ -31,6 +35,7 @@
"region",
"thread",
"threadJoins",
"apron",
"unassume"
],
"context": {
Expand Down Expand Up @@ -74,14 +79,6 @@
"exp": {
"region-offsets": true
},
"witness": {
"enabled": false,
"invariant": {
"loop-head": true,
"after-lock": false,
"other": false
}
},
"solver": "td3",
"sem": {
"unknown_function": {
Expand Down
10 changes: 9 additions & 1 deletion conf/svcomp-yaml.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"float": {
"interval": true
},
"apron": {
"domain": "polyhedra",
"strengthening": true
},
"activated": [
"base",
"threadid",
Expand All @@ -30,7 +34,8 @@
"symb_locks",
"region",
"thread",
"threadJoins"
"threadJoins",
"apron"
],
"context": {
"widen": false
Expand Down Expand Up @@ -76,6 +81,9 @@
"enabled": true
},
"invariant": {
"loop-head": true,
"other": false,
"accessed": false,
"exact": false,
"exclude-vars": [
"tmp\\(___[0-9]+\\)?",
Expand Down
6 changes: 3 additions & 3 deletions scripts/update_suite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def clearline

$goblint = File.join(Dir.getwd,"goblint")
goblintbyte = File.join(Dir.getwd,"goblint.byte")
if File.exists?(goblintbyte) then
if File.exist?(goblintbyte) then
puts "Running the byte-code version! Continue? (y/n)"
exit unless $stdin.gets()[0] == 'y'
$goblint = goblintbyte
Expand All @@ -50,11 +50,11 @@ def clearline
end
$vrsn = `#{$goblint} --version`

if not File.exists? "linux-headers" then
if not File.exist? "linux-headers" then
puts "Missing linux-headers, will download now!"
`make headers`
end
has_linux_headers = File.exists? "linux-headers" # skip kernel tests if make headers failed (e.g. on opam-repository opam-ci where network is forbidden)
has_linux_headers = File.exist? "linux-headers" # skip kernel tests if make headers failed (e.g. on opam-repository opam-ci where network is forbidden)

#Command line parameters
#Either only run a single test, or
Expand Down
42 changes: 27 additions & 15 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ struct
Int (if AD.is_bot (AD.meet p1 p2) then ID.of_int ik BI.zero else match eq p1 p2 with Some x when x -> ID.of_int ik BI.one | _ -> bool_top ik)
| Ne ->
Int (if AD.is_bot (AD.meet p1 p2) then ID.of_int ik BI.one else match eq p1 p2 with Some x when x -> ID.of_int ik BI.zero | _ -> bool_top ik)
| IndexPI when AD.to_string p2 = ["all_index"] ->
addToAddrOp p1 (ID.top_of (Cilfacade.ptrdiff_ikind ()))
| _ -> VD.top ()
end
(* For other values, we just give up! *)
Expand Down Expand Up @@ -1043,7 +1045,6 @@ struct
else if AD.may_be_null adr
then M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer");
AD.map (add_offset_varinfo (convert_offset a gs st ofs)) adr
| Bot -> AD.bot ()
| _ ->
M.debug ~category:Analyzer "Failed evaluating %a to lvalue" d_lval lval;
AD.unknown_ptr
Expand Down Expand Up @@ -1251,14 +1252,9 @@ struct
(* ignore @@ printf "BlobSize %a MayPointTo %a\n" d_plainexp e VD.pretty p; *)
match p with
| Address a ->
let has_offset = function
| `NoOffset -> false
| `Field _
| `Index _ -> true
in
(* If there's a non-heap var or an offset in the lval set, we answer with bottom *)
if AD.exists (function
| Addr (v,o) -> (not @@ ctx.ask (Queries.IsHeapVar v)) || has_offset o
| Addr (v,o) -> (not @@ ctx.ask (Queries.IsHeapVar v)) || o <> `NoOffset
| _ -> false) a then
Queries.Result.bot q
else (
Expand Down Expand Up @@ -1997,17 +1993,23 @@ struct
let st' = invalidate ~deep:false ~ctx (Analyses.ask_of_ctx ctx) gs st shallow_addrs in
invalidate ~deep:true ~ctx (Analyses.ask_of_ctx ctx) gs st' deep_addrs

let check_free_of_non_heap_mem ctx special_fn ptr =
let check_invalid_mem_dealloc ctx special_fn ptr =
let has_non_heap_var = AD.exists (function
| Addr (v,_) -> not (ctx.ask (Q.IsHeapVar v))
| _ -> false)
in
let has_non_zero_offset = AD.exists (function
| Addr (_,o) -> Offs.cmp_zero_offset o <> `MustZero
| _ -> false)
in
match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local ptr with
| Address a ->
if AD.is_top a then
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Points-to set for pointer %a in function %s is top. Potential free of non-dynamically allocated memory may occur" d_exp ptr special_fn.vname
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Points-to set for pointer %a in function %s is top. Potentially invalid memory deallocation may occur" d_exp ptr special_fn.vname
else if has_non_heap_var a then
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Free of non-dynamically allocated memory in function %s for pointer %a" special_fn.vname d_exp ptr
else if has_non_zero_offset a then
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 761] "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr
| _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname

let special ctx (lv:lval option) (f: varinfo) (args: exp list) =
Expand Down Expand Up @@ -2283,15 +2285,25 @@ struct
then AD.join addr AD.null_ptr (* calloc can fail and return NULL *)
else addr in
let ik = Cilfacade.ptrdiff_ikind () in
let blobsize = ID.mul (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st size) (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st n) in
(* the memory that was allocated by calloc is set to bottom, but we keep track that it originated from calloc, so when bottom is read from memory allocated by calloc it is turned to zero *)
set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(add_null (AD.of_var heap_var), TVoid [], Array (CArrays.make (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.one) (Blob (VD.bot (), blobsize, false))));
(eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_mval (heap_var, `Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.zero, `NoOffset)))))]
let sizeval = eval_int (Analyses.ask_of_ctx ctx) gs st size in
let countval = eval_int (Analyses.ask_of_ctx ctx) gs st n in
if ID.to_int countval = Some Z.one then (
set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [
add_null (AD.of_var heap_var), TVoid [], Blob (VD.bot (), sizeval, false);
eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_var heap_var))
]
)
else (
let blobsize = ID.mul (ID.cast_to ik @@ sizeval) (ID.cast_to ik @@ countval) in
(* the memory that was allocated by calloc is set to bottom, but we keep track that it originated from calloc, so when bottom is read from memory allocated by calloc it is turned to zero *)
set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(add_null (AD.of_var heap_var), TVoid [], Array (CArrays.make (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.one) (Blob (VD.bot (), blobsize, false))));
(eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_mval (heap_var, `Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.zero, `NoOffset)))))]
)
| _ -> st
end
| Realloc { ptr = p; size }, _ ->
(* Realloc shouldn't be passed non-dynamically allocated memory *)
check_free_of_non_heap_mem ctx f p;
check_invalid_mem_dealloc ctx f p;
begin match lv with
| Some lv ->
let ask = Analyses.ask_of_ctx ctx in
Expand Down Expand Up @@ -2325,7 +2337,7 @@ struct
end
| Free ptr, _ ->
(* Free shouldn't be passed non-dynamically allocated memory *)
check_free_of_non_heap_mem ctx f ptr;
check_invalid_mem_dealloc ctx f ptr;
st
| Assert { exp; refine; _ }, _ -> assert_fn ctx exp refine
| Setjmp { env }, _ ->
Expand Down
Loading

0 comments on commit bb8a926

Please sign in to comment.