Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
367a602
Merge branch 'master' of https://github.com/goblint/analyzer
Robotechnic Jun 26, 2025
a65ac9b
added a check module to get a custom output for the dashboard
Robotechnic Jun 26, 2025
48acfda
exposed the root_with_current function for timing purposes
Robotechnic Jun 25, 2025
e6796da
replaced success by safe
Robotechnic Jun 30, 2025
5edf327
changed lines numbering to start from 0
Robotechnic Jun 30, 2025
4641a2e
added a missing integer overflow success message
Robotechnic Jun 30, 2025
b4b39dd
fixed invalid success checks
Robotechnic Jul 1, 2025
e0a4a98
fixed overflow detection
Robotechnic Jul 9, 2025
8b8d5a7
fixed an anoying message with ranges hash in checks
Robotechnic Jul 19, 2025
7125a02
fixed an issue where safe checks are put on functions
Robotechnic Jul 25, 2025
226284b
Merge branch 'master' of https://github.com/goblint/analyzer into checks
Robotechnic Jul 25, 2025
aabb778
fixed messages according to the last goblint version
Robotechnic Jul 25, 2025
1814a28
Merge branch 'master' of github.com:Robotechnic/analyzer
Robotechnic Jul 29, 2025
fcc97e2
Merge branch 'master' into checks
Robotechnic Jul 29, 2025
c0826cf
added the possibility to add messages to safe
Robotechnic Jul 29, 2025
6e0b95a
removed constant overflow safe checks
Robotechnic Jul 30, 2025
80322bc
fixed a bug with warning messages order
Robotechnic Jul 30, 2025
e2f39e8
Merge branch 'master' of https://github.com/goblint/analyzer
Robotechnic Jul 31, 2025
73a9f0b
Merge branch 'master' into checks
Robotechnic Jul 31, 2025
a56485d
Merge branch 'master' of https://github.com/goblint/analyzer into checks
Robotechnic Aug 1, 2025
7d0c7ec
Merge branch 'master' of https://github.com/goblint/analyzer into checks
Robotechnic Oct 14, 2025
84ed5fc
quoted the paper from which the check.ml file is inspired
Robotechnic Oct 20, 2025
298db2d
Merge branch 'master' into pr/Robotechnic/1838
sim642 Nov 28, 2025
8d46b14
replaced 'let unit in' in arrayDomain
Robotechnic Nov 28, 2025
1d2a46c
added a message to valid check of assertions
Robotechnic Nov 28, 2025
cff6077
added back "dashboard" output kind
Robotechnic Nov 28, 2025
5b26dd0
removed unused type
Robotechnic Dec 2, 2025
9b1aaa8
replaced recursive type in module CheckMap in checks.ml by a non recu…
Robotechnic Dec 2, 2025
d002355
moved the CheckMap related code to the top level of the checks.ml
Robotechnic Dec 2, 2025
0f0c3e3
added documentation to the check_list variable
Robotechnic Dec 2, 2025
ec7564b
fix a wrong function path
Robotechnic Dec 2, 2025
172956a
removed incorrect warnings
Robotechnic Dec 3, 2025
b6ce5f7
removed incorrect warnings
Robotechnic Dec 3, 2025
a3cad06
fixed a typo
Robotechnic Dec 3, 2025
0f1e6b9
fixed a typo
Robotechnic Dec 9, 2025
12c3743
added a missing case in Category of_yojson function
Robotechnic Dec 9, 2025
2d347ed
Merge branch 'master' into checks
sim642 Dec 9, 2025
798b44c
fixed safe messages
Robotechnic Dec 9, 2025
bf9996b
Trim trailing whitespace in Checks
sim642 Dec 9, 2025
04e1c5b
Merge branch 'fork-checks' into checks
Robotechnic Dec 9, 2025
af1acd5
Make safe check messages also format strings
sim642 Dec 9, 2025
2332951
Document Checks in Goblint_lib
sim642 Dec 9, 2025
a91a7f7
Merge branch 'checks-simmo' into checks
sim642 Dec 9, 2025
9316b18
Fix warn_past_end not outputting checks in ArrayDomain
sim642 Dec 9, 2025
475acce
Add checks.json to .gitignore
sim642 Dec 12, 2025
c3ba196
Remove questionable current_node condition for safe checks
sim642 Dec 12, 2025
6d5ec33
Remove questionable no_safe condition for int overflow safe checks
sim642 Dec 12, 2025
3266e4d
Simplify Checks code
sim642 Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ gobview_out/*
witness.yml
witness.certificate.yml

# checks
checks.json

# transformations
transformed.c

Expand Down
4 changes: 4 additions & 0 deletions src/analyses/assert.ml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ struct
match Queries.eval_bool (Analyses.ask_of_man man) e with
| `Lifted false ->
assert_msg Error "Assertion \"%a\" will fail." CilType.Exp.pretty e;
Checks.error Checks.Category.AssertionFailure "Assertion \"%a\" will fail." CilType.Exp.pretty e;
if refine then raise Analyses.Deadcode else man.local
| `Lifted true ->
assert_msg Success "Assertion \"%a\" will succeed" CilType.Exp.pretty e;
Checks.safe_msg Checks.Category.AssertionFailure "Assertion \"%a\" will succeed" CilType.Exp.pretty e;
man.local
| `Bot ->
M.error ~category:Assert "Assertion \"%a\" produces a bottom. What does that mean? (currently uninitialized arrays' content is bottom)" CilType.Exp.pretty e;
Checks.error Checks.Category.AssertionFailure "Assertion \"%a\" produces a bottom. What does that mean? (currently uninitialized arrays' content is bottom)" CilType.Exp.pretty e;
man.local
| `Top ->
assert_msg Warning "Assertion \"%a\" is unknown." CilType.Exp.pretty e;
Checks.warn Checks.Category.AssertionFailure "Assertion \"%a\" is unknown." CilType.Exp.pretty e;
man.local

let special man (lval: lval option) (f:varinfo) (args:exp list) : D.t =
Expand Down
57 changes: 39 additions & 18 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -202,19 +202,25 @@ struct
fun x y ->
(match ID.equal_to Z.zero y with
| `Eq ->
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division is zero"
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division is zero";
Checks.error Checks.Category.DivisionByZero "Second argument of division is zero"
| `Top ->
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division might be zero"
| `Neq -> ());
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of division might be zero";
Checks.warn Checks.Category.DivisionByZero "Second argument of division might be zero"
| `Neq ->
Checks.safe Checks.Category.DivisionByZero);
ID.div x y
| Mod ->
fun x y ->
(match ID.equal_to Z.zero y with
| `Eq ->
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo is zero"
M.error ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo is zero";
Checks.error Checks.Category.DivisionByZero "Second argument of modulo is zero"
| `Top ->
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo might be zero"
| `Neq -> ());
M.warn ~category:M.Category.Integer.div_by_zero ~tags:[CWE 369] "Second argument of modulo might be zero";
Checks.warn Checks.Category.DivisionByZero "Second argument of modulo might be zero"
| `Neq ->
Checks.safe Checks.Category.DivisionByZero);
ID.rem x y
| Lt -> ID.lt
| Gt -> ID.gt
Expand Down Expand Up @@ -1092,19 +1098,24 @@ struct
(
if AD.is_null adr then (
AnalysisStateUtil.set_mem_safety_flag InvalidDeref;
M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer"
M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer";
Checks.error Checks.Category.InvalidMemoryAccess "Must dereference NULL pointer"
)
else if AD.may_be_null adr then (
AnalysisStateUtil.set_mem_safety_flag InvalidDeref;
M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer"
M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer";
Checks.warn Checks.Category.InvalidMemoryAccess "May dereference NULL pointer"
) else (
Checks.safe Checks.Category.InvalidMemoryAccess
);
(* Warn if any of the addresses contains a non-local and non-global variable *)
if AD.exists (function
| AD.Addr.Addr (v, _) -> not (CPA.mem v st.cpa) && not (is_global (Analyses.ask_of_man man) v)
| _ -> false
) adr then (
AnalysisStateUtil.set_mem_safety_flag InvalidDeref;
M.warn "lval %a points to a non-local variable. Invalid pointer dereference may occur" d_lval lval
M.warn "lval %a points to a non-local variable. Invalid pointer dereference may occur" d_lval lval;
Checks.warn Checks.Category.InvalidMemoryAccess "lval %a points to a non-local variable. Invalid pointer dereference may occur" d_lval lval
)
);
AD.map (add_offset_varinfo (convert_offset ~man st ofs)) adr
Expand Down Expand Up @@ -1176,10 +1187,11 @@ struct
let eval_funvar man fval: Queries.AD.t =
let fp = eval_fv ~man man.local fval in
if AD.is_top fp then (
if AD.cardinal fp = 1 then
M.warn ~category:Imprecise ~tags:[Category Call] "Unknown call to function %a." d_exp fval
else
M.warn ~category:Imprecise ~tags:[Category Call] "Function pointer %a may contain unknown functions." d_exp fval
if AD.cardinal fp = 1 then (
M.warn ~category:Imprecise ~tags:[Category Call] "Unknown call to function %a." d_exp fval;
) else (
M.warn ~category:Imprecise ~tags:[Category Call] "Function pointer %a may contain unknown functions." d_exp fval;
)
);
fp

Expand Down Expand Up @@ -2223,7 +2235,9 @@ struct
end

let special_unknown_invalidate man f args =
(if CilType.Varinfo.equal f dummyFunDec.svar then M.warn ~category:Imprecise ~tags:[Category Call] "Unknown function ptr called");
(if CilType.Varinfo.equal f dummyFunDec.svar then (
M.warn ~category:Imprecise ~tags:[Category Call] "Unknown function ptr called";
));
let desc = LF.find f in
let shallow_addrs = LibraryDesc.Accesses.find desc.accs { kind = Write; deep = false } args in
let deep_addrs = LibraryDesc.Accesses.find desc.accs { kind = Write; deep = true } args in
Expand Down Expand Up @@ -2259,17 +2273,23 @@ struct
| Address a ->
if AD.is_top a then (
AnalysisStateUtil.set_mem_safety_flag InvalidFree;
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
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;
Checks.warn Checks.Category.InvalidMemoryAccess "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 (
AnalysisStateUtil.set_mem_safety_flag InvalidFree;
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
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;
Checks.warn Checks.Category.InvalidMemoryAccess "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 (
AnalysisStateUtil.set_mem_safety_flag InvalidFree;
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:(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;
Checks.warn Checks.Category.InvalidMemoryAccess "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr
) else (
Checks.safe Checks.Category.InvalidMemoryAccess
)
| _ ->
AnalysisStateUtil.set_mem_safety_flag InvalidFree;
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Pointer %a in function %s doesn't evaluate to a valid address. Invalid memory deallocation may occur" d_exp ptr special_fn.vname
M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Pointer %a in function %s doesn't evaluate to a valid address. Invalid memory deallocation may occur" d_exp ptr special_fn.vname;
Checks.warn Checks.Category.InvalidMemoryAccess "Pointer %a in function %s doesn't evaluate to a valid address. Invalid memory deallocation may occur" d_exp ptr special_fn.vname

let points_to_heap_only man ptr =
match man.ask (Queries.MayPointTo ptr) with
Expand Down Expand Up @@ -2327,6 +2347,7 @@ struct
end
| _ ->
(M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr;
Checks.warn Checks.Category.InvalidMemoryAccess "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr;
`Top)

let special man (lv:lval option) (f: varinfo) (args: exp list) =
Expand Down
6 changes: 4 additions & 2 deletions src/analyses/baseInvariant.ml
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,11 @@ struct
let warn_and_top_on_zero x =
if GobOption.exists (Z.equal Z.zero) (ID.to_int x) then
(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";
Checks.error Checks.Category.DivisionByZero "Must Undefined Behavior: Second argument of div or mod is 0, continuing with top";
ID.top_of ikind)
else
x
else (
Checks.safe Checks.Category.DivisionByZero;
x)
in
let meet_bin a' b' = id_meet_down ~old:a ~c:a', id_meet_down ~old:b ~c:b' in
let meet_com oi = (* commutative *)
Expand Down
Loading
Loading