Skip to content

Commit 1b95f9b

Browse files
authored
Merge pull request #6040 from padhi-aws-forks/memset_null_fix
[smt2_convt] Fix invalid and NULL pointer handling
2 parents b233b7e + 7663a57 commit 1b95f9b

File tree

5 files changed

+79
-4
lines changed

5 files changed

+79
-4
lines changed

regression/cbmc/memset_null/main.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <stdlib.h>
2+
#include <string.h>
3+
4+
void main()
5+
{
6+
char *data = nondet() ? NULL : malloc(8);
7+
memset(data, 0, 8);
8+
memset(data, 0, 8);
9+
}

regression/cbmc/memset_null/test.desc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
4+
^\[main.precondition_instance.1\] line .* memset destination region writeable: FAILURE$
5+
^\[main.precondition_instance.2\] line .* memset destination region writeable: FAILURE$
6+
^EXIT=10$
7+
^SIGNAL=0$
8+
^VERIFICATION FAILED$
9+
--
10+
--
11+
This test case checks that byte operations (e.g. memset) oninvalid and `NULL`
12+
pointers are correctly encoded in SMT2.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <stdlib.h>
2+
3+
void main()
4+
{
5+
assert(NULL != (NULL + 1));
6+
assert(NULL != (NULL - 1));
7+
8+
int offset;
9+
__CPROVER_assume(offset != 0);
10+
assert(NULL != (NULL + offset));
11+
12+
assert(NULL - NULL == 0);
13+
14+
int *ptr;
15+
assert(ptr - NULL == 0);
16+
ptr = NULL;
17+
assert((ptr - 1) + 1 == NULL);
18+
19+
ptr = nondet() ? NULL : malloc(1);
20+
assert((ptr - 1) + 1 == (NULL + 1) - 1);
21+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.c
3+
4+
^\[main.assertion.1\] line .* assertion \(void \*\)0 != \(void \*\)0 \+ \(.*\)1: SUCCESS$
5+
^\[main.assertion.2\] line .* assertion \(void \*\)0 != \(void \*\)0 - \(.*\)1: SUCCESS$
6+
^\[main.assertion.3\] line .* assertion \(void \*\)0 != \(void \*\)0 \+ \(.*\)offset: SUCCESS$
7+
^\[main.assertion.4\] line .* assertion \(void \*\)0 - \(void \*\)0 == \(.*\)0: SUCCESS$
8+
^\[main.assertion.5\] line .* assertion ptr - \(void \*\)0 == \(.*\)0: FAILURE$
9+
^\[main.assertion.6\] line .* assertion \(ptr - \(.*\)1\) \+ \(.*\)1 == \(\(.* \*\)NULL\): SUCCESS$
10+
^\[main.assertion.7\] line .* assertion \(ptr - \(.*\)1\) \+ \(.*\)1 == \(\(.* \*\)NULL\): FAILURE$
11+
^EXIT=10$
12+
^SIGNAL=0$
13+
^VERIFICATION FAILED$
14+
--
15+
--
16+
This test case checks that pointer arithmetic on NULL pointers are correctly
17+
encoded by the SMT2 translation routines.

src/solvers/smt2/smt2_conv.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3175,18 +3175,29 @@ void smt2_convt::convert_plus(const plus_exprt &expr)
31753175
p.type().id() == ID_pointer,
31763176
"one of the operands should have pointer type");
31773177

3178-
const auto element_size = pointer_offset_size(expr.type().subtype(), ns);
3179-
CHECK_RETURN(element_size.has_value() && *element_size >= 1);
3178+
mp_integer element_size;
3179+
if(expr.type().subtype().id() == ID_empty)
3180+
{
3181+
// This is a gcc extension.
3182+
// https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
3183+
element_size = 1;
3184+
}
3185+
else
3186+
{
3187+
auto element_size_opt = pointer_offset_size(expr.type().subtype(), ns);
3188+
CHECK_RETURN(element_size_opt.has_value() && *element_size_opt >= 1);
3189+
element_size = *element_size_opt;
3190+
}
31803191

31813192
out << "(bvadd ";
31823193
convert_expr(p);
31833194
out << " ";
31843195

3185-
if(*element_size >= 2)
3196+
if(element_size >= 2)
31863197
{
31873198
out << "(bvmul ";
31883199
convert_expr(i);
3189-
out << " (_ bv" << *element_size << " " << boolbv_width(expr.type())
3200+
out << " (_ bv" << element_size << " " << boolbv_width(expr.type())
31903201
<< "))";
31913202
}
31923203
else
@@ -4249,6 +4260,11 @@ void smt2_convt::set_to(const exprt &expr, bool value)
42494260
if(expr.id() == ID_equal && value)
42504261
{
42514262
const equal_exprt &equal_expr=to_equal_expr(expr);
4263+
if(equal_expr.lhs().type().id() == ID_empty)
4264+
{
4265+
// ignore equality checking over expressions with empty (void) type
4266+
return;
4267+
}
42524268

42534269
if(equal_expr.lhs().id()==ID_symbol)
42544270
{

0 commit comments

Comments
 (0)