Skip to content

Commit b9ff8d6

Browse files
Goto checker interfaces
1 parent 0fede8f commit b9ff8d6

14 files changed

+381
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ set_target_properties(
5858
goto-analyzer-lib
5959
goto-cc
6060
goto-cc-lib
61+
goto-checker
6162
goto-diff
6263
goto-diff-lib
6364
goto-instrument

jbmc/src/jbmc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ target_link_libraries(jbmc-lib
1212
ansi-c
1313
big-int
1414
cbmc-lib
15+
goto-checker
1516
goto-instrument-lib
1617
goto-programs
1718
goto-symex

jbmc/src/jbmc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ OBJ += ../$(CPROVER_DIR)/src/ansi-c/ansi-c$(LIBEXT) \
66
../java_bytecode/java_bytecode$(LIBEXT) \
77
../$(CPROVER_DIR)/src/linking/linking$(LIBEXT) \
88
../$(CPROVER_DIR)/src/big-int/big-int$(LIBEXT) \
9+
../$(CPROVER_DIR)/src/goto-checker/goto-checker$(LIBEXT) \
910
../$(CPROVER_DIR)/src/goto-programs/goto-programs$(LIBEXT) \
1011
../$(CPROVER_DIR)/src/goto-symex/goto-symex$(LIBEXT) \
1112
../$(CPROVER_DIR)/src/pointer-analysis/value_set$(OBJEXT) \

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ add_subdirectory(ansi-c)
8585
add_subdirectory(assembler)
8686
add_subdirectory(big-int)
8787
add_subdirectory(cpp)
88+
add_subdirectory(goto-checker)
8889
add_subdirectory(goto-programs)
8990
add_subdirectory(goto-symex)
9091
add_subdirectory(jsil)

src/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ DIRS = analyses \
66
cpp \
77
goto-analyzer \
88
goto-cc \
9+
goto-checker \
910
goto-diff \
1011
goto-instrument \
1112
goto-programs \
@@ -49,9 +50,11 @@ goto-instrument.dir: languages goto-programs.dir pointer-analysis.dir \
4950
goto-symex.dir linking.dir analyses.dir solvers.dir \
5051
json.dir
5152

53+
goto-checker.dir: solvers.dir goto-symex.dir goto-programs.dir
54+
5255
cbmc.dir: languages solvers.dir goto-symex.dir analyses.dir \
5356
pointer-analysis.dir goto-programs.dir linking.dir \
54-
goto-instrument.dir
57+
goto-instrument.dir goto-checker.dir
5558

5659
goto-analyzer.dir: languages analyses.dir goto-programs.dir linking.dir \
5760
json.dir goto-instrument.dir

src/cbmc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \
1616
../cpp/cpp$(LIBEXT) \
1717
../linking/linking$(LIBEXT) \
1818
../big-int/big-int$(LIBEXT) \
19+
../goto-checker/goto-checker$(LIBEXT) \
1920
../goto-programs/goto-programs$(LIBEXT) \
2021
../goto-symex/goto-symex$(LIBEXT) \
2122
../pointer-analysis/value_set$(OBJEXT) \

src/goto-checker/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
file(GLOB_RECURSE sources "*.cpp" "*.h")
2+
add_library(goto-checker ${sources})
3+
4+
generic_includes(goto-checker)
5+
6+
target_link_libraries(goto-checker goto-programs goto-symex solvers util)

src/goto-checker/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
SRC = property_checker.cpp \
2+
safety_checker.cpp \
3+
# Empty last line
4+
5+
INCLUDES= -I ..
6+
7+
include ../config.inc
8+
include ../common
9+
10+
CLEANFILES = goto-checker$(LIBEXT)
11+
12+
all: goto-checker$(LIBEXT)
13+
14+
###############################################################################
15+
16+
goto-checker$(LIBEXT): $(OBJ)
17+
$(LINKLIB)

src/goto-checker/goto_checker.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Checker Interface
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Goto Checker Interface
11+
12+
#include "goto_checker.h"
13+
14+
goto_checkert::goto_checkert(
15+
const optionst &options,
16+
ui_message_handlert &ui_message_handler)
17+
: messaget(ui_message_handler),
18+
options(options),
19+
ui_message_handler(ui_message_handler)
20+
{
21+
}

src/goto-checker/goto_checker.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Checker Interface
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Goto Checker Interface
11+
12+
#ifndef CPROVER_GOTO_CHECKER_GOTO_CHECKER_H
13+
#define CPROVER_GOTO_CHECKER_GOTO_CHECKER_H
14+
15+
#include <goto-programs/goto_trace.h>
16+
17+
#include <util/options.h>
18+
#include <util/ui_message.h>
19+
20+
#include "properties.h"
21+
22+
/// An implementation of `goto_checkert` provides functionality for
23+
/// checking a set of properties and returning counterexamples
24+
/// one by one to the caller.
25+
/// An implementation of `goto_checkert` is responsible for maintaining
26+
/// the state of the analysis that it performs (e.g. goto-symex, solver, etc).
27+
/// It is not responsible for maintaining outcomes (e.g. property results,
28+
/// counterexamples, etc). However, an implementation may restrict the
29+
/// sets of properties it is asked to check (e.g. only sequences of subsets).
30+
class goto_checkert : public messaget
31+
{
32+
public:
33+
/// Check whether the given properties with status UNKNOWN or newly
34+
/// discovered properties hold
35+
/// \return The properties whose status has been determined
36+
/// If there is a property with status FAIL then its counterexample
37+
/// can be retrieved by calling `build_error_trace` before any
38+
/// subsequent call to operator().
39+
/// `goto_checkert` derivatives shall be implemented in a way such
40+
/// that repeated calls to operator() shall return the next FAILed
41+
/// property until eventually not returning any FAILing properties.
42+
virtual propertiest operator()(const propertiest &) = 0;
43+
44+
/// This builds and returns the counterexample
45+
virtual goto_tracet build_error_trace() = 0;
46+
47+
protected:
48+
goto_checkert(
49+
const optionst &options,
50+
ui_message_handlert &ui_message_handler);
51+
52+
const optionst &options;
53+
ui_message_handlert &ui_message_handler;
54+
};
55+
56+
#endif // CPROVER_GOTO_CHECKER_GOTO_CHECKER_H

src/goto-checker/goto_verifier.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Verifier Interface
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Goto Verifier Interface
11+
12+
#include "goto_verifier.h"
13+
14+
goto_verifiert::goto_verifiert(
15+
const optionst &_options,
16+
ui_message_handlert &ui_message_handler)
17+
: messaget(ui_message_handler),
18+
options(_options),
19+
ui_message_handler(ui_message_handler)
20+
{
21+
}

src/goto-checker/goto_verifier.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Verifier Interface
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Goto Verifier Interface
11+
12+
#ifndef CPROVER_GOTO_CHECKER_GOTO_VERIFIER_H
13+
#define CPROVER_GOTO_CHECKER_GOTO_VERIFIER_H
14+
15+
#include <util/optional.h>
16+
#include <util/options.h>
17+
#include <util/ui_message.h>
18+
19+
#include "properties.h"
20+
21+
/// An implementation of `goto_verifiert` checks all properties in
22+
/// a goto model. It typically uses, but doesn't have to use, a
23+
/// `goto_checkert` to iteratively determine the verification result
24+
/// of each property.
25+
class goto_verifiert : public messaget
26+
{
27+
public:
28+
/// Check whether all properties hold.
29+
/// \return PASS if all properties are PASS,
30+
/// FAIL if at least one property is FAIL and no property is ERROR,
31+
/// UNKNOWN if no property is FAIL or ERROR and
32+
/// at least one property is UNKNOWN,
33+
/// ERROR if at least one property is error.
34+
virtual resultt operator()() = 0;
35+
36+
/// Report results
37+
virtual void report() = 0;
38+
39+
/// Returns the properties
40+
const propertiest &get_properties()
41+
{
42+
return properties;
43+
}
44+
45+
protected:
46+
goto_verifiert(
47+
const optionst &options,
48+
ui_message_handlert &ui_message_handler);
49+
50+
const optionst &options;
51+
ui_message_handlert &ui_message_handler;
52+
propertiest properties;
53+
};
54+
55+
#endif // CPROVER_GOTO_CHECKER_GOTO_VERIFIER_H

src/goto-checker/properties.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Checker Interface
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Property Map
11+
12+
#include "properties.h"
13+
14+
#include <util/invariant.h>
15+
16+
std::string as_string(resultt result)
17+
{
18+
switch(result)
19+
{
20+
case resultt::PASS:
21+
return "PASS";
22+
case resultt::FAIL:
23+
return "FAIL";
24+
case resultt::ERROR:
25+
return "ERROR";
26+
case resultt::UNKNOWN:
27+
return "UNKNOWN";
28+
}
29+
30+
UNREACHABLE;
31+
}
32+
33+
/// Returns the properties in the goto model
34+
propertiest initialize_properties(const goto_modelt &goto_model)
35+
{
36+
propertiest properties;
37+
forall_goto_functions(it, goto_model.goto_functions)
38+
{
39+
if(
40+
!it->second.is_inlined() ||
41+
it->first == goto_model.goto_functions.entry_point())
42+
{
43+
const goto_programt &goto_program = it->second.body;
44+
45+
forall_goto_program_instructions(i_it, goto_program)
46+
{
47+
if(!i_it->is_assert())
48+
continue;
49+
50+
const source_locationt &source_location = i_it->source_location;
51+
52+
irep_idt property_id = source_location.get_property_id();
53+
54+
property_infot &property = properties[property_id];
55+
property.result = resultt::UNKNOWN;
56+
property.location = i_it;
57+
}
58+
}
59+
}
60+
return properties;
61+
}
62+
63+
/// Update with the preference order
64+
/// 1. old non-UNKNOWN result
65+
/// 2. new non-UNKNOWN result
66+
/// 3. UNKNOWN
67+
/// Suitable for updating property results
68+
resultt &operator|=(resultt &a, resultt const &b)
69+
{
70+
PRECONDITION(a == resultt::UNKNOWN || a == b);
71+
switch(a)
72+
{
73+
case resultt::UNKNOWN:
74+
a = b;
75+
return a;
76+
case resultt::ERROR:
77+
case resultt::PASS:
78+
case resultt::FAIL:
79+
return a;
80+
}
81+
UNREACHABLE;
82+
}
83+
84+
/// Update with the preference order
85+
/// 1. ERROR
86+
/// 2. FAIL
87+
/// 3. UNKNOWN
88+
/// 4. PASS
89+
/// Suitable for computing overall results
90+
resultt &operator&=(resultt &a, resultt const &b)
91+
{
92+
switch(a)
93+
{
94+
case resultt::UNKNOWN:
95+
a = b;
96+
return a;
97+
case resultt::PASS:
98+
a = (b == resultt::PASS ? a : b);
99+
return a;
100+
case resultt::ERROR:
101+
a = b;
102+
return a;
103+
case resultt::FAIL:
104+
a = (b == resultt::ERROR ? b : a);
105+
return a;
106+
}
107+
UNREACHABLE;
108+
}
109+
110+
/// Determines the overall result corresponding from the given properties
111+
/// That is PASS if all properties are PASS,
112+
/// FAIL if at least one property is FAIL and no property is ERROR,
113+
/// UNKNOWN if no property is FAIL or ERROR and
114+
/// at least one property is UNKNOWN,
115+
/// ERROR if at least one property is error.
116+
resultt determine_result(const propertiest &properties)
117+
{
118+
resultt result = resultt::UNKNOWN;
119+
for(const auto &property_pair : properties)
120+
{
121+
result &= property_pair.second.result;
122+
}
123+
return result;
124+
}
125+
126+
/// Merges a set of properties into a given set of properties,
127+
/// updating its results and adding new properties.
128+
void merge_properties(
129+
propertiest &properties,
130+
const propertiest &updated_properties)
131+
{
132+
for(const auto &property_pair : updated_properties)
133+
{
134+
auto found_property = properties.insert(property_pair);
135+
if(!found_property.second)
136+
found_property.first->second.result |= property_pair.second.result;
137+
}
138+
}

0 commit comments

Comments
 (0)