Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion src/analyses/varEq.ml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ struct
struct
include PartitionDomain.ExpPartitions

let is_str_constant = function
| Const (CStr _ | CWStr _) -> true
| _ -> false

let invariant ~scope ss =
fold (fun s a ->
if B.mem MyCFG.unknown_exp s then
Expand All @@ -25,7 +29,7 @@ struct
let module B_prod = BatSet.Make2 (Exp) (Exp) in
let s_prod = B_prod.cartesian_product s s in
let i = B_prod.Product.fold (fun (x, y) a ->
if Exp.compare x y < 0 && not (InvariantCil.exp_contains_tmp x) && not (InvariantCil.exp_contains_tmp y) && InvariantCil.exp_is_in_scope scope x && InvariantCil.exp_is_in_scope scope y then (* each equality only one way, no self-equalities *)
if Exp.compare x y < 0 && not (InvariantCil.exp_contains_tmp x) && not (InvariantCil.exp_contains_tmp y) && InvariantCil.exp_is_in_scope scope x && InvariantCil.exp_is_in_scope scope y && not (is_str_constant x) && not (is_str_constant y) then (* each equality only one way, no self-equalities *)
let eq = BinOp (Eq, x, y, intType) in
Invariant.(a && of_exp eq)
else
Expand Down
18 changes: 13 additions & 5 deletions src/cdomain/value/domains/invariantCil.ml
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,23 @@ let exp_deep_unroll_types =
let visitor = new exp_deep_unroll_types_visitor in
visitCilExpr visitor

let var_may_be_shadowed scope vi =
let vi_original_name = Cilfacade.find_original_name vi in
let local_may_shadow local =
not (CilType.Varinfo.equal vi local) && (* exclude self-equality by vid because the original names would always equal *)
vi_original_name = Cilfacade.find_original_name local
in
List.exists local_may_shadow scope.sformals || List.exists local_may_shadow scope.slocals

let var_is_in_scope scope vi =
match Cilfacade.find_scope_fundec vi with
| None -> vi.vstorage <> Static (* CIL pulls static locals into globals, but they aren't syntactically in global scope *)
| None ->
vi.vstorage <> Static && (* CIL pulls static locals into globals, but they aren't syntactically in global scope *)
not (var_may_be_shadowed scope vi)
| Some fd ->
if CilType.Fundec.equal fd scope then
GobConfig.get_bool "witness.invariant.all-locals" || (not @@ hasAttribute "goblint_cil_nested" vi.vattr)
else
false
CilType.Fundec.equal fd scope &&
(GobConfig.get_bool "witness.invariant.all-locals" || (not @@ hasAttribute "goblint_cil_nested" vi.vattr)) &&
not (var_may_be_shadowed scope vi) (* TODO: could distinguish non-nested and nested? *)

class exp_is_in_scope_visitor (scope: fundec) (acc: bool ref) = object
inherit nopCilVisitor
Expand Down
1 change: 1 addition & 0 deletions src/util/library/libraryFunctions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ let glibc_desc_list: (string * LibraryDesc.t) list = LibraryDsl.[
("ferror_unlocked", unknown [drop "stream" [r_deep; w_deep]]);
("fwrite_unlocked", unknown [drop "buffer" [r]; drop "size" []; drop "count" []; drop "stream" [r_deep; w_deep]]);
("clearerr_unlocked", unknown [drop "stream" [w]]); (* TODO: why only w? *)
("__fpending", unknown [drop "stream" [r_deep]]);
("futimesat", unknown [drop "dirfd" []; drop "pathname" [r]; drop "times" [r]]);
("error", unknown ((drop "status" []) :: (drop "errnum" []) :: (drop "format" [r]) :: (VarArgs (drop' [r]))));
("warn", unknown (drop "format" [r] :: VarArgs (drop' [r])));
Expand Down
5 changes: 5 additions & 0 deletions tests/regression/56-witness/71-var_eq-str-invariant.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// CRAM PARAM: --set ana.activated[+] var_eq
int main() {
char text = "foobar";
return 0;
}
16 changes: 16 additions & 0 deletions tests/regression/56-witness/71-var_eq-str-invariant.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
$ goblint --set ana.activated[+] var_eq --enable witness.yaml.enabled --enable witness.invariant.other 71-var_eq-str-invariant.c
[Info][Deadcode] Logical lines of code (LLoC) summary:
live: 3
dead: 0
total lines: 3
[Info][Witness] witness generation summary:
location invariants: 0
loop invariants: 0
flow-insensitive invariants: 0
total generation entries: 1

Should not contain invariant with string literal equality:

$ yamlWitnessStrip < witness.yml
- entry_type: invariant_set
content: []
13 changes: 13 additions & 0 deletions tests/regression/56-witness/72-shadowing-invariant.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// CRAM PARAM: --set ana.activated[+] var_eq

int foo = 1;

int main() {
int foo = 2; // shadows global

int bar = 3;
{
int bar = 4; // shadows outer block
return 0;
}
}
71 changes: 71 additions & 0 deletions tests/regression/56-witness/72-shadowing-invariant.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
$ goblint --set ana.activated[+] var_eq --enable witness.yaml.enabled --enable witness.invariant.other 72-shadowing-invariant.c
[Info][Deadcode] Logical lines of code (LLoC) summary:
live: 5
dead: 0
total lines: 5
[Info][Witness] witness generation summary:
location invariants: 6
loop invariants: 0
flow-insensitive invariants: 0
total generation entries: 1

Should not contain invariants containing shadowed variables.
They can be wrong and contradicting.

$ yamlWitnessStrip < witness.yml
- entry_type: invariant_set
content:
- invariant:
type: location_invariant
location:
file_name: 72-shadowing-invariant.c
line: 8
column: 3
function: main
value: 2 == foo
format: c_expression
- invariant:
type: location_invariant
location:
file_name: 72-shadowing-invariant.c
line: 8
column: 3
function: main
value: foo == 2
format: c_expression
- invariant:
type: location_invariant
location:
file_name: 72-shadowing-invariant.c
line: 10
column: 5
function: main
value: 2 == foo
format: c_expression
- invariant:
type: location_invariant
location:
file_name: 72-shadowing-invariant.c
line: 10
column: 5
function: main
value: foo == 2
format: c_expression
- invariant:
type: location_invariant
location:
file_name: 72-shadowing-invariant.c
line: 11
column: 5
function: main
value: 2 == foo
format: c_expression
- invariant:
type: location_invariant
location:
file_name: 72-shadowing-invariant.c
line: 11
column: 5
function: main
value: foo == 2
format: c_expression
Loading