Skip to content

Commit eb4f7a8

Browse files
committed
Model strchr inside string.h
then replace the body to call the refine-string index-of.
1 parent 13c9a17 commit eb4f7a8

23 files changed

+727
-46
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <assert.h>
2+
#include <string.h>
3+
4+
int main()
5+
{
6+
char test[] = "foo";
7+
8+
char *first_o = strchr(test, 'o');
9+
assert(*first_o == test[1]);
10+
assert(*first_o == test[0]);
11+
char *first_t = strchr(test, 't');
12+
assert(*first_t == test[1]);
13+
assert(*first_t == test[0]);
14+
return 0;
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE broken-smt-backend
2+
test.c
3+
--refine-strings --max-nondet-string-length 10
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main.assertion.\d+\] line \d+ assertion \*first_o == test\[1\]: SUCCESS$
7+
^\[main.assertion.\d+\] line \d+ assertion \*first_o == test\[0\]: FAILURE$
8+
^\[main.assertion.\d+\] line \d+ assertion \*first_t == test\[1\]: FAILURE$
9+
^\[main.assertion.\d+\] line \d+ assertion \*first_t == test\[0\]: FAILURE$
10+
^VERIFICATION FAILED$
11+
--
12+
^warning: ignoring
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <assert.h>
2+
#include <string.h>
3+
4+
int main()
5+
{
6+
int i;
7+
char *test = i ? "fo\0tis" : "notfoti";
8+
9+
char *first_o = strchr(test, 'o');
10+
assert(first_o != NULL);
11+
assert(*first_o == test[0]);
12+
return 0;
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE broken-smt-backend
2+
test.c
3+
--refine-strings
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main.assertion.\d+\] line \d+ assertion first_o != (NULL|\(\(void \*\)0\)): SUCCESS$
7+
^\[main.assertion.\d+\] line \d+ assertion \*first_o == test\[0\]: FAILURE$
8+
^VERIFICATION FAILED$
9+
--
10+
^warning: ignoring
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
int main()
6+
{
7+
int size = 4;
8+
char *str = malloc(sizeof(char) * size);
9+
char nondet_char;
10+
__CPROVER_assume(nondet_char != '\0');
11+
str[0] = nondet_char;
12+
char nondet_char2;
13+
__CPROVER_assume(str[1] != '\0');
14+
// str[1] = nondet_char2;
15+
str[2] = 'z';
16+
str[3] = '\0';
17+
char *result = strchr(str, 'z');
18+
assert(result);
19+
__CPROVER_assert(0, "unreachable");
20+
// assert(result == str+1);
21+
// assert(result == str);
22+
23+
return 0;
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE broken-smt-backend
2+
test.c
3+
--refine-strings
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[strchr.assertion.\d+\] line \d+ zero should be present: SUCCESS$
7+
^\[main.assertion.\d+\] line \d+ assertion result: SUCCESS$
8+
^\[main.assertion.\d+\] line \d+ unreachable: FAILURE$
9+
^VERIFICATION FAILED$
10+
--
11+
^warning: ignoring

src/ansi-c/library/cprover.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,9 @@ __CPROVER_bool __CPROVER_overflow_plus();
159159
__CPROVER_bool __CPROVER_overflow_shl();
160160
__CPROVER_bool __CPROVER_overflow_unary_minus();
161161

162+
long __CPROVER_math_func_string_index_of(
163+
const char *haystack,
164+
__CPROVER_size_t length,
165+
char needle);
166+
162167
#endif // CPROVER_ANSI_C_LIBRARY_CPROVER_H

src/ansi-c/library/string.c

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
2+
/* FUNCTION: __CPROVER_math_func_string_index_of */
3+
4+
long __CPROVER_math_func_string_index_of(
5+
const char *haystack,
6+
__CPROVER_size_t length,
7+
char needle)
8+
{
9+
for(__CPROVER_size_t i = 0; i < length; i++)
10+
{
11+
if(haystack[i] == needle)
12+
return i;
13+
}
14+
return -1;
15+
}
16+
117
/* FUNCTION: __builtin___strcpy_chk */
218

319
inline char *__builtin___strcpy_chk(char *dst, const char *src, __CPROVER_size_t s)
@@ -932,9 +948,16 @@ inline int memcmp(const void *s1, const void *s2, size_t n)
932948
#include <string.h>
933949
#define __CPROVER_STRING_H_INCLUDED
934950
#endif
951+
#include <stdint.h> // SIZE_MAX
935952

936953
#undef strchr
937954

955+
__CPROVER_size_t __VERIFIER_nondet___CPROVER_size_t();
956+
long __CPROVER_math_func_string_index_of(
957+
const char *haystack,
958+
__CPROVER_size_t length,
959+
char needle);
960+
938961
inline char *strchr(const char *src, int c)
939962
{
940963
__CPROVER_HIDE:;
@@ -945,14 +968,27 @@ inline char *strchr(const char *src, int c)
945968
__CPROVER_size_t i;
946969
return found?src+i:0;
947970
#else
948-
for(__CPROVER_size_t i=0; ; i++)
949-
{
950-
if(src[i]==(char)c)
951-
return ((char *)src)+i; // cast away const-ness
952-
if(src[i]==0) break;
953-
}
954-
return 0;
955-
#endif
971+
972+
/* for(__CPROVER_size_t i=0; ; i++) */
973+
/* { */
974+
/* if(src[i]==(char)c) */
975+
/* return ((char *)src)+i; // cast away const-ness */
976+
/* if(src[i]==0) break; */
977+
/* } */
978+
/* return 0; */
979+
980+
__CPROVER_size_t src_array_length =
981+
SIZE_MAX; // __VERIFIER_nondet___CPROVER_size_t();
982+
long index_of_zero =
983+
__CPROVER_math_func_string_index_of(src, src_array_length, '\0');
984+
__CPROVER_assert(index_of_zero >= 0, "zero should be present");
985+
long index_of_c =
986+
__CPROVER_math_func_string_index_of(src, src_array_length, (char)c);
987+
if(index_of_c >= 0 && index_of_c < index_of_zero)
988+
return ((char *)src) + (__CPROVER_size_t)index_of_c;
989+
else
990+
return (char *)0;
991+
#endif
956992
}
957993

958994
/* FUNCTION: strrchr */

src/cbmc/cbmc_parse_options.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Author: Daniel Kroening, [email protected]
4949
#include <goto-checker/stop_on_fail_verifier_with_fault_localization.h>
5050

5151
#include <goto-programs/adjust_float_expressions.h>
52+
#include <goto-programs/c_string_refinement.h>
5253
#include <goto-programs/initialize_goto_model.h>
5354
#include <goto-programs/instrument_preconditions.h>
5455
#include <goto-programs/link_to_library.h>
@@ -242,6 +243,8 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
242243

243244
if(cmdline.isset("string-abstraction"))
244245
options.set_option("string-abstraction", true);
246+
if(cmdline.isset("refine-strings"))
247+
options.set_option("refine-strings", true);
245248

246249
if(cmdline.isset("reachability-slice-fb"))
247250
options.set_option("reachability-slice-fb", true);
@@ -363,6 +366,9 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
363366
{
364367
options.set_option("refine-strings", true);
365368
options.set_option("string-printable", cmdline.isset("string-printable"));
369+
options.set_option(
370+
"max-nondet-string-length",
371+
cmdline.get_value("max-nondet-string-length"));
366372
}
367373

368374
if(cmdline.isset("max-node-refinement"))
@@ -872,6 +878,11 @@ bool cbmc_parse_optionst::process_goto_program(
872878

873879
if(options.get_bool_option("string-abstraction"))
874880
string_instrumentation(goto_model, log.get_message_handler());
881+
else if(options.get_bool_option("refine-strings"))
882+
c_string_refinement(
883+
goto_model,
884+
log.get_message_handler(),
885+
options.get_option("max-nondet-string-length"));
875886

876887
// remove function pointers
877888
log.status() << "Removal of function pointers and virtual functions"

src/goto-programs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
SRC = adjust_float_expressions.cpp \
22
builtin_functions.cpp \
3+
c_string_refinement.cpp \
34
class_hierarchy.cpp \
45
class_identifier.cpp \
56
compute_called_functions.cpp \

0 commit comments

Comments
 (0)