Skip to content

Commit 7552bad

Browse files
committed
Add tests for let-expression introduction on double-deref
1 parent 61507bd commit 7552bad

17 files changed

+250
-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+
This deref operator push-in is performed (implicitly) by value_set_dereferencet::dereference, which special-cases
11+
the ternary conditional expression.
12+
More complicated expressions are handled using a let-expression. Example:
13+
14+
p->field1->field2 ==>
15+
((p == &o1 ? o1 : o2).field1)->field2 ==>
16+
let derefd_pointer = ((p == &o1 ? o1 : o2).field1) in (derefd_pointer == &o3 ? o3 : derefd_pointer == &o4 ? o4 : derefd_pointer == &o5 ? o5 : o6)
17+
18+
Symex executes this let-expression as an auxiliary assignment, such as
19+
derefd_pointer = ((p == &o1 ? o1 : o2).field1)
20+
result = (derefd_pointer == &o3 ? o3 : derefd_pointer == &o4 ? o4 : derefd_pointer == &o5 ? o5 : o6)
21+
22+
The tests in this directory check that auxiliary let-expressions like this are only used when appropriate by inspecting formula VCCs:
23+
double_deref.desc -- a directly nested double-dereference, should not use a let-expression
24+
double_deref_with_cast.desc -- a double-deref with an intervening cast (*(int*)*p for example), should use a let-expression
25+
double_deref_with_member.desc -- a double-deref with an intervening member expression (p->field1->field2), should use a let-expression
26+
double_deref_with_pointer_arithmetic.desc -- a double-deref with intervening pointer arithmetic (p[idx1][idx2]), should use a let-expression
27+
*_single_alias.desc -- variants of the above where the first dereference points to a single possible object, so no let-expression is necessary
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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
struct container
6+
{
7+
int *iptr;
8+
};
9+
10+
int main(int argc, char **argv)
11+
{
12+
struct container *cptr;
13+
struct container container1, container2;
14+
container1.iptr = (int *)malloc(sizeof(int));
15+
*container1.iptr = 1;
16+
container2.iptr = (int *)malloc(sizeof(int));
17+
*container2.iptr = 2;
18+
19+
cptr = (argc == 1 ? &container1 : &container2);
20+
21+
assert(*(cptr->iptr) == argc);
22+
}
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
struct container
6+
{
7+
int *iptr;
8+
};
9+
10+
int main(int argc, char **argv)
11+
{
12+
struct container *cptr;
13+
struct container container1;
14+
container1.iptr = (int *)malloc(sizeof(int));
15+
*container1.iptr = 1;
16+
17+
cptr = &container1;
18+
19+
assert(*(cptr->iptr) == argc);
20+
}
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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
#include <assert.h>
3+
#include <stdlib.h>
4+
5+
struct container
6+
{
7+
int *iptr;
8+
};
9+
10+
int main(int argc, char **argv)
11+
{
12+
int **new_ptrs = malloc(2 * sizeof(int *));
13+
int *iptr1 = (int *)malloc(sizeof(int));
14+
*iptr1 = 1;
15+
int *iptr2 = (int *)malloc(sizeof(int));
16+
*iptr2 = 2;
17+
18+
new_ptrs[argc % 2] = iptr1;
19+
new_ptrs[1 - (argc % 2)] = iptr2;
20+
21+
assert(*(new_ptrs[argc % 2]) == argc);
22+
}
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: 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+
{
7+
int *iptr;
8+
};
9+
10+
int main(int argc, char **argv)
11+
{
12+
int **new_ptrs = malloc(2 * sizeof(int *));
13+
int *iptr1 = (int *)malloc(sizeof(int));
14+
*iptr1 = 1;
15+
16+
new_ptrs[argc % 2] = iptr1;
17+
18+
assert(*(new_ptrs[argc % 2]) == 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_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)