Skip to content

Commit edf0639

Browse files
committed
Add tests for let-expression introduction on double-deref
1 parent c4edd76 commit edf0639

17 files changed

+246
-0
lines changed

regression/cbmc/double_deref/README

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
This is a batch of tests checking cbmc's behaviour against expressions with more than one deref
2+
operator, such as **p, *(int*)*p, p->field1->field2, etc. At present a directly nested dereference
3+
(**p) is handled by pushing the second deref inside the result of the first. Example:
4+
5+
**p ==>
6+
*(p == &o1 ? o1 : o2) ==>
7+
(p == &o1 ? *o1 : *o2) ==>
8+
(p == &o1 ? (o1 == &o3 ? o3 : o4) : (o2 == &o5 ? o5 : o6))
9+
10+
More complicated expressions are handled using a let-expression. Example:
11+
12+
p->field1->field2 ==>
13+
((p == &o1 ? o1 : o2).field1)->field2 ==>
14+
(simplify) (p == &o1 ? o1.field1 : o2.field1)->field2 ==>
15+
let derefd_pointer = (p == &o1 ? o1.field1 : o2.field1) in (derefd_pointer == &o3 ? o3 : derefd_pointer == &o4 ? o4 : derefd_pointer == &o5 ? o5 : o6)
16+
17+
Symex executes this let-expression as an auxiliary assignment, such as
18+
derefd_pointer = (p == &o1 ? o1.field1 : o2.field1)
19+
result = (derefd_pointer == &o3 ? o3 : derefd_pointer == &o4 ? o4 : derefd_pointer == &o5 ? o5 : o6)
20+
21+
The tests in this directory check that auxiliary let-expressions like this are only used when appropriate by inspecting formula VCCs:
22+
double_deref.desc -- a directly nested double-dereference, should not use a let-expression
23+
double_deref_with_cast.desc -- a double-deref with an intervening cast (*(int*)*p for example), should use a let-expression
24+
double_deref_with_member.desc -- a double-deref with an intervening member expression (p->field1->field2), should use a let-expression
25+
double_deref_with_pointer_arithmetic.desc -- a double-deref with intervening pointer arithmetic (p[idx1][idx2]), should use a let-expression
26+
*_single_alias.desc -- variants of the above where the first dereference points to a single possible object, so no let-expression is necessary
27+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
int main(int argc, char **argv) {
6+
7+
int **pptr;
8+
int *ptr1 = (int*)malloc(sizeof(int));
9+
*ptr1 = 1;
10+
int *ptr2 = (int*)malloc(sizeof(int));
11+
*ptr2 = 2;
12+
13+
pptr = (argc == 5 ? &ptr1 : &ptr2);
14+
15+
assert(**pptr == argc);
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref.c
3+
--show-vcc
4+
\{1\} \(main::1::pptr!0@1#2 = address_of\(main::1::ptr[12]!0@1\) \? main::argc!0@1#1 = [12] : main::argc!0@1#1 = [12]\)
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
derefd_pointer::derefd_pointer
9+
--
10+
See README for details about these tests
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
int main(int argc, char **argv) {
6+
7+
int **pptr;
8+
int *ptr1 = (int*)malloc(sizeof(int));
9+
*ptr1 = 1;
10+
11+
pptr = &ptr1;
12+
13+
assert(**pptr == argc);
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref_single_alias.c
3+
--show-vcc
4+
\{1\} main::argc!0@1#1 = 1
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
derefd_pointer::derefd_pointer
9+
--
10+
See README for details about these tests
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
int main(int argc, char **argv) {
6+
7+
void **pptr;
8+
int *ptr1 = (int*)malloc(sizeof(int));
9+
*ptr1 = 1;
10+
int *ptr2 = (int*)malloc(sizeof(int));
11+
*ptr2 = 2;
12+
13+
pptr = (argc == 1 ? &ptr1 : &ptr2);
14+
15+
assert(*(int*)*pptr == argc);
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref_with_cast.c
3+
--show-vcc
4+
^\{-[0-9]+\} derefd_pointer::derefd_pointer!0#1 =
5+
^\{1\} \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object[1-9]+\) \? main::argc!0@1#1 = [12] : main::argc!0@1#1 = [12]
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
--
10+
See README for details about these tests
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
int main(int argc, char **argv) {
6+
7+
void **pptr;
8+
int *ptr1 = (int*)malloc(sizeof(int));
9+
*ptr1 = 1;
10+
11+
pptr = &ptr1;
12+
13+
assert(*(int*)*pptr == argc);
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref_with_cast_single_alias.c
3+
--show-vcc
4+
\{1\} main::argc!0@1#1 = 1
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
derefd_pointer::derefd_pointer
9+
--
10+
See README for details about these tests
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
struct container {
6+
int *iptr;
7+
};
8+
9+
int main(int argc, char **argv) {
10+
11+
struct container *cptr;
12+
struct container container1, container2;
13+
container1.iptr = (int*)malloc(sizeof(int));
14+
*container1.iptr = 1;
15+
container2.iptr = (int*)malloc(sizeof(int));
16+
*container2.iptr = 2;
17+
18+
cptr = (argc == 1 ? &container1 : &container2);
19+
20+
assert(*(cptr->iptr) == argc);
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref_with_member.c
3+
--show-vcc
4+
^\{-[0-9]+\} derefd_pointer::derefd_pointer!0#1 = \(main::1::cptr!0@1#2 = address_of\(main::1::container[12]!0@1\) \? address_of\(symex_dynamic::dynamic_object[12]\) : address_of\(symex_dynamic::dynamic_object[12]\)\)
5+
^\{1\} \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object[12]\) \? main::argc!0@1#1 = 2 : main::argc!0@1#1 = 1\)
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
--
10+
See README for details about these tests
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
struct container {
6+
int *iptr;
7+
};
8+
9+
int main(int argc, char **argv) {
10+
11+
struct container *cptr;
12+
struct container container1;
13+
container1.iptr = (int*)malloc(sizeof(int));
14+
*container1.iptr = 1;
15+
16+
cptr = &container1;
17+
18+
assert(*(cptr->iptr) == argc);
19+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref_with_member_single_alias.c
3+
--show-vcc
4+
\{1\} main::argc!0@1#1 = 1
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
derefd_pointer::derefd_pointer
9+
--
10+
See README for details about these tests
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
struct container {
6+
int *iptr;
7+
};
8+
9+
int main(int argc, char **argv) {
10+
11+
int **new_ptrs = malloc(2 * sizeof(int*));
12+
int *iptr1 = (int*)malloc(sizeof(int));
13+
*iptr1 = 1;
14+
int *iptr2 = (int*)malloc(sizeof(int));
15+
*iptr2 = 2;
16+
17+
new_ptrs[argc % 2] = iptr1;
18+
new_ptrs[1 - (argc % 2)] = iptr2;
19+
20+
assert(*(new_ptrs[argc % 2]) == argc);
21+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref_with_pointer_arithmetic.c
3+
--show-vcc
4+
^\{-[0-9]+\} derefd_pointer::derefd_pointer!0#1 = symex_dynamic::dynamic_object1#3\[cast\(mod #source_location=""\(main::argc!0@1#1, 2\), signedbv\[64\]\)\]
5+
^\{1\} \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object[23]\) \? main::argc!0@1#1 = 2 : main::argc!0@1#1 = 1\)
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
--
10+
See README for details about these tests
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
struct container {
6+
int *iptr;
7+
};
8+
9+
int main(int argc, char **argv) {
10+
11+
int **new_ptrs = malloc(2 * sizeof(int*));
12+
int *iptr1 = (int*)malloc(sizeof(int));
13+
*iptr1 = 1;
14+
15+
new_ptrs[argc % 2] = iptr1;
16+
17+
assert(*(new_ptrs[argc % 2]) == argc);
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
double_deref_with_pointer_arithmetic_single_alias.c
3+
--show-vcc
4+
\{1\} main::argc!0@1#1 = 1
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
derefd_pointer::derefd_pointer
9+
--
10+
See README for details about these tests

0 commit comments

Comments
 (0)