Skip to content

Commit f23f4f3

Browse files
Merge pull request #3794 from peterschrammel/multi-path-symex-only-checker
Multi-path symex-only checker [blocks: 3795]
2 parents 99015ad + 3809454 commit f23f4f3

13 files changed

+336
-4
lines changed

jbmc/src/java_bytecode/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SRC = bytecode_info.cpp \
77
generic_parameter_specialization_map_keys.cpp \
88
jar_file.cpp \
99
jar_pool.cpp \
10+
java_bmc_util.cpp \
1011
java_bytecode_convert_class.cpp \
1112
java_bytecode_convert_method.cpp \
1213
java_bytecode_concurrency_instrumentation.cpp \
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*******************************************************************\
2+
3+
Module: Bounded Model Checking Utils for Java
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Bounded Model Checking Utils for Java
11+
12+
#include "java_bmc_util.h"
13+
14+
#include <goto-checker/symex_bmc.h>
15+
#include <goto-programs/abstract_goto_model.h>
16+
#include <java_bytecode/java_enum_static_init_unwind_handler.h>
17+
18+
void java_setup_symex(
19+
const optionst &options,
20+
abstract_goto_modelt &goto_model,
21+
symex_bmct &symex)
22+
{
23+
// unwinds <clinit> loops to number of enum elements
24+
if(options.get_bool_option("java-unwind-enum-static"))
25+
{
26+
// clang-format off
27+
// (it asks for the body to be at the same indent level as the parameters
28+
// for some reason)
29+
symex.add_loop_unwind_handler(
30+
[&goto_model](
31+
const goto_symex_statet::call_stackt &context,
32+
unsigned loop_num,
33+
unsigned unwind,
34+
unsigned &max_unwind)
35+
{ // NOLINT (*)
36+
return java_enum_static_init_unwind_handler(
37+
context, loop_num, unwind, max_unwind, goto_model.get_symbol_table());
38+
});
39+
// clang-format on
40+
}
41+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*******************************************************************\
2+
3+
Module: Bounded Model Checking Utils for Java
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Bounded Model Checking Utils for Java
11+
12+
#ifndef CPROVER_JAVA_BYTECODE_JAVA_BMC_UTIL_H
13+
#define CPROVER_JAVA_BYTECODE_JAVA_BMC_UTIL_H
14+
15+
class abstract_goto_modelt;
16+
class optionst;
17+
class symex_bmct;
18+
19+
/// Registers Java-specific preprocessing handlers with goto-symex
20+
void java_setup_symex(
21+
const optionst &options,
22+
abstract_goto_modelt &goto_model,
23+
symex_bmct &symex);
24+
25+
#endif // CPROVER_JAVA_BYTECODE_JAVA_BMC_UTIL_H
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Checker using Bounded Model Checking for Java
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Goto Checker using Bounded Model Checking for Java
11+
12+
#ifndef CPROVER_JAVA_BYTECODE_JAVA_MULTI_PATH_SYMEX_ONLY_CHECKER_H
13+
#define CPROVER_JAVA_BYTECODE_JAVA_MULTI_PATH_SYMEX_ONLY_CHECKER_H
14+
15+
#include <goto-checker/multi_path_symex_only_checker.h>
16+
17+
#include "java_bmc_util.h"
18+
19+
class java_multi_path_symex_only_checkert
20+
: public multi_path_symex_only_checkert
21+
{
22+
public:
23+
java_multi_path_symex_only_checkert(
24+
const optionst &options,
25+
ui_message_handlert &ui_message_handler,
26+
abstract_goto_modelt &goto_model)
27+
: multi_path_symex_only_checkert(options, ui_message_handler, goto_model)
28+
{
29+
java_setup_symex(options, goto_model, symex);
30+
}
31+
};
32+
33+
#endif // CPROVER_JAVA_BYTECODE_JAVA_MULTI_PATH_SYMEX_ONLY_CHECKER_H

jbmc/src/java_bytecode/module_dependencies.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
analyses
22
ansi-c # should go away
3+
goto-checker
34
goto-programs
45
java_bytecode
56
json

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Author: Daniel Kroening, [email protected]
2727

2828
#include <ansi-c/ansi_c_language.h>
2929

30+
#include <goto-checker/all_properties_verifier.h>
31+
3032
#include <goto-programs/adjust_float_expressions.h>
3133
#include <goto-programs/lazy_goto_model.h>
3234
#include <goto-programs/instrument_preconditions.h>
@@ -60,6 +62,7 @@ Author: Daniel Kroening, [email protected]
6062
#include <java_bytecode/convert_java_nondet.h>
6163
#include <java_bytecode/java_bytecode_language.h>
6264
#include <java_bytecode/java_enum_static_init_unwind_handler.h>
65+
#include <java_bytecode/java_multi_path_symex_only_checker.h>
6366
#include <java_bytecode/remove_exceptions.h>
6467
#include <java_bytecode/remove_instanceof.h>
6568
#include <java_bytecode/remove_java_new.h>
@@ -563,6 +566,19 @@ int jbmc_parse_optionst::doit()
563566
goto_model.validate(validation_modet::INVARIANT);
564567
}
565568

569+
if(
570+
options.get_bool_option("program-only") ||
571+
options.get_bool_option("show-vcc"))
572+
{
573+
if(!options.get_bool_option("paths"))
574+
{
575+
all_properties_verifiert<java_multi_path_symex_only_checkert> verifier(
576+
options, ui_message_handler, goto_model);
577+
(void)verifier();
578+
return CPROVER_EXIT_SUCCESS;
579+
}
580+
}
581+
566582
// The `configure_bmc` callback passed will enable enum-unwind-static if
567583
// applicable.
568584
return bmct::do_language_agnostic_bmc(

src/cbmc/cbmc_parse_options.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ Author: Daniel Kroening, [email protected]
3030

3131
#include <cpp/cprover_library.h>
3232

33+
#include <goto-checker/all_properties_verifier.h>
3334
#include <goto-checker/bmc_util.h>
35+
#include <goto-checker/multi_path_symex_only_checker.h>
36+
#include <goto-checker/properties.h>
3437

3538
#include <goto-programs/adjust_float_expressions.h>
3639
#include <goto-programs/initialize_goto_model.h>
@@ -553,6 +556,19 @@ int cbmc_parse_optionst::doit()
553556
goto_model.validate(validation_modet::INVARIANT);
554557
}
555558

559+
if(
560+
options.get_bool_option("program-only") ||
561+
options.get_bool_option("show-vcc"))
562+
{
563+
if(!options.get_bool_option("paths"))
564+
{
565+
all_properties_verifiert<multi_path_symex_only_checkert> verifier(
566+
options, ui_message_handler, goto_model);
567+
(void)verifier();
568+
return CPROVER_EXIT_SUCCESS;
569+
}
570+
}
571+
556572
return bmct::do_language_agnostic_bmc(
557573
options, goto_model, ui_message_handler);
558574
}

src/goto-checker/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
SRC = bmc_util.cpp \
22
incremental_goto_checker.cpp \
33
goto_verifier.cpp \
4+
multi_path_symex_only_checker.cpp \
45
properties.cpp \
56
report_util.cpp \
67
solver_factory.cpp \

src/goto-checker/bmc_util.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,53 @@ void slice(
225225
<< " remaining after simplification" << messaget::eom;
226226
}
227227

228+
std::vector<irep_idt> update_properties_status_from_symex_target_equation(
229+
propertiest &properties,
230+
const symex_target_equationt &equation)
231+
{
232+
std::vector<irep_idt> updated_properties;
233+
234+
for(const auto &step : equation.SSA_steps)
235+
{
236+
if(!step.is_assert())
237+
continue;
238+
239+
irep_idt property_id = step.get_property_id();
240+
241+
if(property_id.empty())
242+
continue;
243+
244+
// Don't set false properties; we wouldn't have traces for them.
245+
const auto status = step.cond_expr.is_true() ? property_statust::PASS
246+
: property_statust::UNKNOWN;
247+
auto emplace_result = properties.emplace(
248+
property_id, property_infot{step.source.pc, step.comment, status});
249+
250+
if(emplace_result.second)
251+
{
252+
updated_properties.push_back(property_id);
253+
}
254+
else
255+
{
256+
property_infot &property_info = emplace_result.first->second;
257+
property_statust old_status = property_info.status;
258+
property_info.status |= status;
259+
260+
if(property_info.status != old_status)
261+
updated_properties.push_back(property_id);
262+
}
263+
}
264+
265+
for(auto &property_pair : properties)
266+
{
267+
if(property_pair.second.status == property_statust::NOT_CHECKED)
268+
{
269+
// This could be a NOT_CHECKED, NOT_REACHABLE or PASS,
270+
// but the equation doesn't give us precise information.
271+
property_pair.second.status = property_statust::PASS;
272+
updated_properties.push_back(property_pair.first);
273+
}
274+
}
275+
276+
return updated_properties;
277+
}

src/goto-checker/bmc_util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Author: Daniel Kroening, Peter Schrammel
1616

1717
#include <goto-programs/safety_checker.h>
1818

19+
#include "properties.h"
20+
1921
class goto_tracet;
2022
class memory_model_baset;
2123
class message_handlert;
@@ -67,6 +69,13 @@ void slice(
6769
const optionst &,
6870
ui_message_handlert &);
6971

72+
/// Sets property status to PASS for properties whose
73+
/// conditions are constant true.
74+
/// \return IDs of updated properties
75+
std::vector<irep_idt> update_properties_status_from_symex_target_equation(
76+
propertiest &properties,
77+
const symex_target_equationt &equation);
78+
7079
// clang-format off
7180
#define OPT_BMC \
7281
"(program-only)" \
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Checker using Multi-Path Symbolic Execution Only
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Goto Checker using Multi-Path Symbolic Execution only (no SAT solving)
11+
12+
#include "multi_path_symex_only_checker.h"
13+
14+
#include <util/invariant.h>
15+
16+
#include <goto-symex/memory_model_pso.h>
17+
#include <goto-symex/show_program.h>
18+
#include <goto-symex/show_vcc.h>
19+
20+
#include "bmc_util.h"
21+
22+
multi_path_symex_only_checkert::multi_path_symex_only_checkert(
23+
const optionst &options,
24+
ui_message_handlert &ui_message_handler,
25+
abstract_goto_modelt &goto_model)
26+
: incremental_goto_checkert(options, ui_message_handler),
27+
goto_model(goto_model),
28+
ns(goto_model.get_symbol_table(), symex_symbol_table),
29+
symex(
30+
ui_message_handler,
31+
goto_model.get_symbol_table(),
32+
equation,
33+
options,
34+
path_storage)
35+
{
36+
setup_symex(symex, ns, options, ui_message_handler);
37+
}
38+
39+
incremental_goto_checkert::resultt multi_path_symex_only_checkert::
40+
operator()(propertiest &properties)
41+
{
42+
perform_symex();
43+
44+
output_coverage_report();
45+
46+
if(options.get_bool_option("show-vcc"))
47+
{
48+
show_vcc(options, ui_message_handler, equation);
49+
}
50+
51+
if(options.get_bool_option("program-only"))
52+
{
53+
show_program(ns, equation);
54+
}
55+
56+
return resultt(
57+
resultt::progresst::DONE,
58+
update_properties_status_from_symex_target_equation(properties, equation));
59+
}
60+
61+
void multi_path_symex_only_checkert::perform_symex()
62+
{
63+
auto get_goto_function =
64+
[this](const irep_idt &id) -> const goto_functionst::goto_functiont & {
65+
return goto_model.get_goto_function(id);
66+
};
67+
68+
// perform symbolic execution
69+
symex.symex_from_entry_point_of(get_goto_function, symex_symbol_table);
70+
71+
// add a partial ordering, if required
72+
// We won't be able to decide any properties by adding this,
73+
// but we'd like to see the entire SSA.
74+
if(equation.has_threads())
75+
{
76+
std::unique_ptr<memory_model_baset> memory_model =
77+
get_memory_model(options, ns);
78+
memory_model->set_message_handler(ui_message_handler);
79+
(*memory_model)(equation);
80+
}
81+
82+
log.statistics() << "size of program expression: "
83+
<< equation.SSA_steps.size() << " steps" << messaget::eom;
84+
85+
slice(symex, equation, ns, options, ui_message_handler);
86+
}
87+
88+
void multi_path_symex_only_checkert::output_coverage_report()
89+
{
90+
std::string cov_out = options.get_option("symex-coverage-report");
91+
if(
92+
!cov_out.empty() &&
93+
symex.output_coverage_report(goto_model.get_goto_functions(), cov_out))
94+
{
95+
log.error() << "Failed to write symex coverage report to '" << cov_out
96+
<< "'" << messaget::eom;
97+
}
98+
}

0 commit comments

Comments
 (0)