Skip to content

Commit d23aa7e

Browse files
author
Daniel Kroening
authored
Merge pull request #795 from tautschnig/array-replace
Implement C library string functions via array_{copy,replace,set}
2 parents 928c28f + ed0c88f commit d23aa7e

30 files changed

+638
-208
lines changed

regression/cbmc/byte_update8/main.c

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int x=0x01020304;
6+
short *p=((short*)&x)+1;
7+
*p=0xABCD;
8+
assert(x==0xABCD0304);
9+
p=(short*)(((char*)&x)+1);
10+
*p=0xABCD;
11+
assert(x==0xABABCD04);
12+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc/byte_update9/main.c

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int x=0x01020304;
6+
short *p=((short*)&x)+1;
7+
*p=0xABCD;
8+
assert(x==0x0102ABCD);
9+
p=(short*)(((char*)&x)+1);
10+
*p=0xABCD;
11+
assert(x==0x01ABCDCD);
12+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--big-endian
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <stdlib.h>
2+
3+
int *array;
4+
5+
int main()
6+
{
7+
unsigned size;
8+
__CPROVER_assume(size==1);
9+
10+
// produce unbounded array that does not have byte granularity
11+
array=malloc(size*sizeof(int));
12+
array[0]=0x01020304;
13+
14+
int array0=array[0];
15+
__CPROVER_assert(array0==0x01020304, "array[0] matches");
16+
17+
char *p=(char *)array;
18+
char p0=p[0];
19+
char p1=p[1];
20+
char p2=p[2];
21+
char p3=p[3];
22+
__CPROVER_assert(p0==4, "p[0] matches");
23+
__CPROVER_assert(p1==3, "p[1] matches");
24+
__CPROVER_assert(p2==2, "p[2] matches");
25+
__CPROVER_assert(p3==1, "p[3] matches");
26+
27+
unsigned short *q=(unsigned short *)array;
28+
unsigned short q0=q[0];
29+
__CPROVER_assert(q0==0x0304, "p[0,1] matches");
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--little-endian
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc/memset1/main.c

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <string.h>
2+
#include <stdlib.h>
3+
#include <assert.h>
4+
5+
int main()
6+
{
7+
int A[5];
8+
memset(A, 0, sizeof(int)*5);
9+
assert(A[0]==0);
10+
assert(A[1]==0);
11+
assert(A[2]==0);
12+
assert(A[3]==0);
13+
assert(A[4]==0);
14+
15+
A[3]=42;
16+
memset(A, 0xFFFFFF01, sizeof(int)*3);
17+
assert(A[0]==0x01010101);
18+
assert(A[1]==0x01010111);
19+
assert(A[2]==0x01010101);
20+
assert(A[3]==42);
21+
assert(A[4]==0);
22+
23+
int *B=malloc(sizeof(int)*2);
24+
memset(B, 2, sizeof(int)*2);
25+
assert(B[0]==0x02020202);
26+
assert(B[1]==0x02020202);
27+
28+
return 0;
29+
}

regression/cbmc/memset1/test.desc

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
\[main.assertion.7\] assertion A\[1\]==0x01010111: FAILURE
8+
\*\* 1 of 12 failed \(2 iterations\)
9+
--
10+
^warning: ignoring

src/ansi-c/ansi_c_internal_additions.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,11 @@ void ansi_c_internal_additions(std::string &code)
244244
// arrays
245245
// NOLINTNEXTLINE(whitespace/line_length)
246246
"__CPROVER_bool __CPROVER_array_equal(const void *array1, const void *array2);\n"
247+
// overwrite all of *dest (possibly using nondet values), even
248+
// if *src is smaller
247249
"void __CPROVER_array_copy(const void *dest, const void *src);\n"
250+
// replace at most size-of-*src bytes in *dest
251+
"void __CPROVER_array_replace(const void *dest, const void *src);\n"
248252
"void __CPROVER_array_set(const void *dest, ...);\n"
249253

250254
// k-induction

src/ansi-c/c_typecheck_expr.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -2473,10 +2473,12 @@ exprt c_typecheck_baset::do_special_functions(
24732473
throw 0;
24742474
}
24752475

2476-
exprt pointer_offset_expr=exprt(ID_pointer_offset, expr.type());
2477-
pointer_offset_expr.operands()=expr.arguments();
2476+
exprt pointer_offset_expr=pointer_offset(expr.arguments().front());
24782477
pointer_offset_expr.add_source_location()=source_location;
24792478

2479+
if(expr.type()!=pointer_offset_expr.type())
2480+
pointer_offset_expr.make_typecast(expr.type());
2481+
24802482
return pointer_offset_expr;
24812483
}
24822484
else if(identifier==CPROVER_PREFIX "POINTER_OBJECT")

src/ansi-c/expr2c.cpp

+36-3
Original file line numberDiff line numberDiff line change
@@ -3824,6 +3824,9 @@ std::string expr2ct::convert_code(
38243824
if(statement==ID_array_copy)
38253825
return convert_code_array_copy(src, indent);
38263826

3827+
if(statement==ID_array_replace)
3828+
return convert_code_array_replace(src, indent);
3829+
38273830
if(statement=="set_may" ||
38283831
statement=="set_must")
38293832
return
@@ -4225,6 +4228,39 @@ std::string expr2ct::convert_code_array_copy(
42254228

42264229
/*******************************************************************\
42274230
4231+
Function: expr2ct::convert_code_array_replace
4232+
4233+
Inputs:
4234+
4235+
Outputs:
4236+
4237+
Purpose:
4238+
4239+
\*******************************************************************/
4240+
4241+
std::string expr2ct::convert_code_array_replace(
4242+
const codet &src,
4243+
unsigned indent)
4244+
{
4245+
std::string dest=indent_str(indent)+"ARRAY_REPLACE(";
4246+
4247+
forall_operands(it, src)
4248+
{
4249+
unsigned p;
4250+
std::string arg_str=convert_with_precedence(*it, p);
4251+
4252+
if(it!=src.operands().begin())
4253+
dest+=", ";
4254+
dest+=arg_str;
4255+
}
4256+
4257+
dest+=");";
4258+
4259+
return dest;
4260+
}
4261+
4262+
/*******************************************************************\
4263+
42284264
Function: expr2ct::convert_code_assert
42294265
42304266
Inputs:
@@ -4673,9 +4709,6 @@ std::string expr2ct::convert_with_precedence(
46734709
else if(src.id()=="buffer_size")
46744710
return convert_function(src, "BUFFER_SIZE", precedence=16);
46754711

4676-
else if(src.id()==ID_pointer_offset)
4677-
return convert_function(src, "POINTER_OFFSET", precedence=16);
4678-
46794712
else if(src.id()==ID_isnan)
46804713
return convert_function(src, "isnan", precedence=16);
46814714

src/ansi-c/expr2c_class.h

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ class expr2ct
204204
std::string convert_code_output(const codet &src, unsigned indent);
205205
std::string convert_code_array_set(const codet &src, unsigned indent);
206206
std::string convert_code_array_copy(const codet &src, unsigned indent);
207+
std::string convert_code_array_replace(const codet &src, unsigned indent);
207208

208209
virtual std::string convert_with_precedence(
209210
const exprt &src, unsigned &precedence);

src/ansi-c/library/cprover.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ void CBMC_trace(int lvl, const char *event, ...);
5252
#endif
5353

5454
// pointers
55-
//unsigned __CPROVER_POINTER_OBJECT(const void *p);
55+
unsigned __CPROVER_POINTER_OBJECT(const void *p);
5656
signed __CPROVER_POINTER_OFFSET(const void *p);
5757
__CPROVER_bool __CPROVER_DYNAMIC_OBJECT(const void *p);
5858
#if 0
@@ -104,7 +104,8 @@ float __CPROVER_fabsf(float);
104104
// arrays
105105
//__CPROVER_bool __CPROVER_array_equal(const void *array1, const void *array2);
106106
void __CPROVER_array_copy(const void *dest, const void *src);
107-
//void __CPROVER_array_set(const void *dest, ...);
107+
void __CPROVER_array_set(const void *dest, ...);
108+
void __CPROVER_array_replace(const void *dest, const void *src);
108109

109110
#if 0
110111
// k-induction

src/ansi-c/library/stdlib.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,18 @@ inline void *malloc(__CPROVER_size_t malloc_size);
6767
inline void *calloc(__CPROVER_size_t nmemb, __CPROVER_size_t size)
6868
{
6969
__CPROVER_HIDE:;
70-
__CPROVER_size_t total_size=nmemb*size;
7170
void *res;
72-
res=malloc(total_size);
71+
res=malloc(nmemb*size);
7372
#ifdef __CPROVER_STRING_ABSTRACTION
7473
__CPROVER_is_zero_string(res)=1;
7574
__CPROVER_zero_string_length(res)=0;
7675
//for(int i=0; i<nmemb*size; i++) res[i]=0;
7776
#else
78-
// there should be memset here
79-
//char *p=res;
80-
//for(int i=0; i<total_size; i++) p[i]=0;
77+
if(nmemb>1)
78+
__CPROVER_array_set(res, 0);
79+
else if(nmemb==1)
80+
for(__CPROVER_size_t i=0; i<size; ++i)
81+
((char*)res)[i]=0;
8182
#endif
8283
return res;
8384
}

0 commit comments

Comments
 (0)