Skip to content

Unwind using GOTO unwinder #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
May 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0d0d8c1
Keep track of unwinding on a per-function basis.
FrNecas Apr 2, 2022
a5e0e82
Remove old unwinder API TODOs
FrNecas Apr 2, 2022
3b0ae8a
Remove unused unwind method
FrNecas Apr 2, 2022
06ba0a5
Refactor unwinder modes into an enum
FrNecas Apr 2, 2022
111b417
Make loopt protected in ssa_unwinder
FrNecas Apr 2, 2022
ed6ac92
Implement an interface for a general unwinder
FrNecas Apr 2, 2022
9e66037
Setup interface for GOTO unwinder
FrNecas Apr 2, 2022
564dd7d
Pass goto_modelt to summary checkers
FrNecas Apr 2, 2022
af8914f
Implement GOTO unwinding and unwind marking
FrNecas Apr 2, 2022
b729c97
Add the possibility of overriding an SSA in db
FrNecas Apr 2, 2022
335cffa
Implement SSA updates based on GOTO unwinding
FrNecas Apr 2, 2022
015f979
Implement conditional switching between unwinders
FrNecas Apr 2, 2022
011ecc3
Do not rely on location numbers in unwinder
FrNecas Apr 3, 2022
fb986c1
Enable KNOWNBUGs which already work
FrNecas Apr 3, 2022
e475c94
Split chained dereferences for assertions
viktormalik Apr 5, 2022
56fa6ae
Fix off-by-one in can_reuse_symderef
FrNecas Apr 6, 2022
3b41004
Initialize local unwinders based on GOTO
FrNecas Apr 6, 2022
a0659cb
Make malloc guard unwindable
FrNecas Apr 7, 2022
ea91e33
Do not create constraints for dynamic memory
FrNecas Apr 13, 2022
347d205
Rename dynamic objects after unwinding
FrNecas Apr 8, 2022
66b2630
Fix missing virtual destructor error from CI
FrNecas Apr 15, 2022
09f06c8
Fix list_iter regression tests
FrNecas Apr 15, 2022
6e744bd
Enable list_unwind tests
FrNecas Apr 15, 2022
ecbdcab
Fix heap-data/shared_mem2 test
FrNecas Apr 20, 2022
4dc10b1
Add more regression tests for heap + k-induction
FrNecas Apr 15, 2022
66b0ddd
Make memory leak analysis sound when unwinding
FrNecas Apr 17, 2022
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
40 changes: 40 additions & 0 deletions regression/heap-data/calendar_false/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
extern int __VERIFIER_nondet_int();
extern void __VERIFIER_error() __attribute__ ((__noreturn__));

#include <stdlib.h>

#define APPEND(l,i) {i->next=l; l=i;}

typedef struct node {
struct node *next;
int event1;
int event2;
} Node;

int main() {
Node *l = NULL;

while (__VERIFIER_nondet_int()) {
int ev1 = __VERIFIER_nondet_int();
int ev2 = __VERIFIER_nondet_int();
if (ev1 < 0 || ev1 > 3 || ev2 < 0 || ev2 > 3)
continue;

if (((ev1 == 0) && (ev2 == 2)) || ((ev1 == 0) && (ev2 == 3)))
continue;

Node *p = malloc(sizeof(*p));
p->event1 = ev1;
p->event2 = ev2;
APPEND(l,p)
}

Node *i = l;

while (i != NULL) {
if (((i->event1 == 1) && (i->event2 == 3)) || ((i->event1 == 0) && (i->event2 == 2)))
__VERIFIER_error();
i = i->next;
}
}

6 changes: 6 additions & 0 deletions regression/heap-data/calendar_false/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CORE
main.c
--heap --values-refine --k-induction
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
40 changes: 40 additions & 0 deletions regression/heap-data/min_max_false/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
extern int __VERIFIER_nondet_int();
extern void __VERIFIER_error() __attribute__ ((__noreturn__));

#include <stdlib.h>
#include <limits.h>

#define APPEND(l,i) {i->next=l; l=i;}

typedef struct node {
struct node *next;
int val;
} Node;

int main() {
Node *l = NULL;
int min = INT_MAX, max = -INT_MAX;

while (__VERIFIER_nondet_int()) {
Node *p = malloc(sizeof(*p));
p->val = __VERIFIER_nondet_int();
APPEND(l, p)

if (min < p->val) {
min = p->val;
}
if (max > p->val) {
max = p->val;
}

}

Node *i = l;
while (i != NULL) {
if (i->val < min)
__VERIFIER_error();
if (i->val > max)
__VERIFIER_error();
i = i->next;
}
}
6 changes: 6 additions & 0 deletions regression/heap-data/min_max_false/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CORE
main.c
--heap --values-refine --k-induction
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
87 changes: 87 additions & 0 deletions regression/heap-data/packet_filter_false/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
extern unsigned __VERIFIER_nondet_uint();
extern int __VERIFIER_nondet_int();
extern char *__VERIFIER_nondet_charp();
extern void __VERIFIER_error() __attribute__ ((__noreturn__));

#include <stdlib.h>

#define LOW 0
#define HIGH 1

typedef struct packet {
unsigned size;
unsigned prio;
unsigned index;
char *payload;
} Packet;

typedef struct packet_list_node {
struct packet packet;
struct packet_list_node *next;
} *Node;

struct packet_queue {
struct packet_list_node *front;
};


Packet receive() {
Packet packet;
static unsigned index = 0;
index++;
packet.size = __VERIFIER_nondet_uint();
packet.prio = __VERIFIER_nondet_int() ? LOW : HIGH;
packet.payload = __VERIFIER_nondet_charp();
packet.index = index;
return packet;
}

extern void send(struct packet p);

void append_to_queue(Packet p, Node *q) {
Node node = malloc(sizeof(*node));
node->packet = p;
node->next = *q;
*q = node;
}

void process_prio_queue(Node q) {
for (Node node = q; node != NULL; node = node->next) {
if (!(node->packet.prio == HIGH || node->packet.size < 500))
__VERIFIER_error();
send(node->packet);
}
}

void process_normal_queue(Node q) {
for (Node node = q; node != NULL; node = node->next) {
if (!(node->packet.prio == LOW && node->packet.size >= 500))
__VERIFIER_error();
send(node->packet);
}
}

int main() {
Node prio_queue = NULL;
Node normal_queue = NULL;

while (__VERIFIER_nondet_int()) {
Packet new_packet = receive();
if (new_packet.size > 0) {
if (new_packet.index > 4) {
append_to_queue(new_packet, &prio_queue);
} else if (new_packet.prio == HIGH) {
append_to_queue(new_packet, &prio_queue);
} else if (new_packet.size < 500) {
append_to_queue(new_packet, &prio_queue);
} else {
append_to_queue(new_packet, &normal_queue);
}
}
}

process_prio_queue(prio_queue);
process_normal_queue(normal_queue);

return 0;
}
6 changes: 6 additions & 0 deletions regression/heap-data/packet_filter_false/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
THOROUGH
main.c
--heap --values-refine --k-induction
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
2 changes: 1 addition & 1 deletion regression/heap-data/running_example_assume/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
KNOWNBUG
CORE
main.c
--heap --values-refine
^EXIT=0$
Expand Down
35 changes: 35 additions & 0 deletions regression/heap-data/running_example_false/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
extern int __VERIFIER_nondet_int();
extern void __VERIFIER_error() __attribute__ ((__noreturn__));

#include <stdlib.h>

typedef struct node {
int val;
struct node *next;
} Node;

int main() {
Node *p, *list = malloc(sizeof(*list));
Node *tail = list;
list->next = NULL;
list->val = 10;
while (__VERIFIER_nondet_int()) {
int x;
if (x < 10 || x > 20) continue;
p = malloc(sizeof(*p));
tail->next = p;
p->next = NULL;
p->val = x;
tail = p;
}

while (1) {
for (p = list; p!= NULL; p = p->next) {
if (!(p->val <= 20 && p->val >= 10))
__VERIFIER_error();
if (p->val < 20) p->val--;
else p->val /= 2;
}
}
}

6 changes: 6 additions & 0 deletions regression/heap-data/running_example_false/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CORE
main.c
--heap --values-refine --k-induction
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
51 changes: 51 additions & 0 deletions regression/heap-data/shared_mem1_false/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
extern int __VERIFIER_nondet_int();
extern void __VERIFIER_error() __attribute__ ((__noreturn__));

#include <stdlib.h>

struct mem {
int val;
};

struct list_node {
int x;
struct mem *mem;
struct list_node *next;
};

int main() {
struct mem *m = malloc(sizeof(*m));
m->val = 100;

struct list_node *head = malloc(sizeof(*head));
head->x = 1;
head->mem = m;
head->next = head;

struct list_node *list = head;

int i = 0;
while (__VERIFIER_nondet_int()) {
int x = __VERIFIER_nondet_int();
if (x > 0 && x < 10) {
struct list_node *n = malloc(sizeof(*n));
n->x = x+i;
n->mem = m;
n->next = head;
list->next = n;
i++;
}
}

list = head;
while (list) {
if (list->mem->val <= 100)
list->mem->val += list->x;
else
list->mem->val -= list->x;
list = list->next;

if (!(m->val > 90 && m->val < 110))
__VERIFIER_error();
}
}
6 changes: 6 additions & 0 deletions regression/heap-data/shared_mem1_false/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CORE
main.c
--heap --values-refine --k-induction
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
3 changes: 2 additions & 1 deletion regression/heap-data/shared_mem2/main.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
extern int __VERIFIER_nondet_int();
extern void __VERIFIER_error() __attribute__ ((__noreturn__));

#include <stdlib.h>

Expand Down Expand Up @@ -41,5 +42,5 @@ int main() {
list = list->next;
}
if (!(m->val == 100))
__VERIFIER_nondet_int();
__VERIFIER_error();
}
6 changes: 3 additions & 3 deletions regression/heap/array_unwind1/test.desc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
KNOWNBUG
CORE
main.c
--incremental-bmc --heap-interval
--incremental-bmc --heap --intervals
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
^\[main\.assertion\.1\] assertion \*a\[0\]==0: OK
^\[main\.assertion\.1\] assertion \*a\[0\]==0: SUCCESS
^\[main\.assertion\.2\] assertion \*a\[1\]==2: FAILURE
6 changes: 3 additions & 3 deletions regression/heap/array_unwind2/test.desc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
KNOWNBUG
CORE
main.c
--incremental-bmc --heap-interval
--incremental-bmc --heap --intervals
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
^\[main\.assertion\.1\] assertion \*a\[0\]==1: FAILURE
^\[main\.assertion\.2\] assertion \*a\[1\]==1: OK
^\[main\.assertion\.2\] assertion \*a\[1\]==1: SUCCESS
8 changes: 4 additions & 4 deletions regression/heap/list_iter1/test.desc
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
KNOWNBUG
CORE
main.c
--incremental-bmc --independent-properties --heap-interval
--incremental-bmc --independent-properties --heap --intervals
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
^\[main\.assertion\.1\] assertion l->n->x==0: OK
^\[main\.assertion\.1\] assertion l->n->x==0: SUCCESS
^\[main\.assertion\.2\] assertion l->n->x==1: FAILURE
^\[main\.assertion\.3\] assertion l->x==2: FAILURE
^\[main\.assertion\.4\] assertion l->x==1: OK
^\[main\.assertion\.4\] assertion l->x==1: SUCCESS
10 changes: 5 additions & 5 deletions regression/heap/list_iter2/test.desc
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
KNOWNBUG
CORE
main.c
--incremental-bmc --independent-properties --heap-interval
--incremental-bmc --independent-properties --heap --intervals
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
^\[main\.assertion\.1\] assertion l->n->x==0: OK
^\[main\.assertion\.2\] assertion l->n->x==1: FAILURE
^\[main\.assertion\.1\] assertion l->n->x==0: FAILURE
^\[main\.assertion\.2\] assertion l->n->x==1: SUCCESS
^\[main\.assertion\.3\] assertion l->x==2: FAILURE
^\[main\.assertion\.4\] assertion l->x==1: OK
^\[main\.assertion\.4\] assertion l->x==1: FAILURE
2 changes: 1 addition & 1 deletion regression/heap/list_iter3/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct list

void main()
{
struct list *l;
struct list *l=NULL;
struct list *nl1=malloc(sizeof(struct list));
nl1->x=-1;
nl1->n=l;
Expand Down
10 changes: 5 additions & 5 deletions regression/heap/list_iter3/test.desc
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
KNOWNBUG
CORE
main.c
--incremental-bmc --independent-properties --heap-interval
--incremental-bmc --independent-properties --heap --intervals
^EXIT=10$
^SIGNAL=0$
^VERIFICATION FAILED$
^\[main\.assertion\.1\] assertion l->n->x==0: OK
^\[main\.assertion\.2\] assertion l->n->x==1: FAILURE
^\[main\.assertion\.1\] assertion l->n->x==0: FAILURE
^\[main\.assertion\.2\] assertion l->n->x==1: SUCCESS
^\[main\.assertion\.3\] assertion l->x==2: FAILURE
^\[main\.assertion\.4\] assertion l->x==1: OK
^\[main\.assertion\.4\] assertion l->x==1: FAILURE
Loading