Skip to content

Commit 2760b9b

Browse files
Set paths-symex-explore-all when unwinding-assertions defaults to true
When unwinding-assertions is enabled by default (via set_default_analysis_flags), paths-symex-explore-all must also be enabled. Otherwise, the single-path symex checker's has_finished_exploration check can return true before any path is explored, because dynamically generated properties (like 'no body for callee') don't exist in the initial properties map. The explicit --unwinding-assertions flag already set paths-symex-explore-all (line 192), but the default enablement path did not, causing --paths lifo to miss no-body assertions. Also fix two pre-existing bugs exposed by the exploration fix: - --outfile with an invalid path was silently ignored in --paths mode because the solver (and thus the file) was never created when all VCCs were simplified away. Add early outfile validation. - --sat-solver with an invalid name was silently ignored for the same reason. Add early solver name validation in parse_sat_options. Five tests previously tagged paths-lifo-expected-failure now pass with --paths lifo, so remove the tag from those. Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
1 parent 7a4df92 commit 2760b9b

10 files changed

Lines changed: 54 additions & 6 deletions

File tree

regression/cbmc/Array_operations4/program-only.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE paths-lifo-expected-failure
1+
CORE
22
main.c
33
--program-only
44
target!0@1#2 ==

regression/cbmc/array-cell-sensitivity15/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE paths-lifo-expected-failure
1+
CORE
22
access.c
33
--program-only
44
^EXIT=0$

regression/cbmc/cover-failed-assertions/test-no-failed-assertions.desc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ test.c
1313
--
1414
This is checking that without the --cover-failed-assertions flag we still get the same result as we did before adding
1515
it in this example.
16+
--paths mode explores one path at a time, so individual paths may not cover all blocks.

regression/cbmc/cover-failed-assertions/test.desc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ test.c
1111
^warning: ignoring
1212
--
1313
This is checking that the if statement body can actually be covered with the new flag
14+
--paths mode explores one path at a time, so individual paths may not cover all blocks.

regression/cbmc/fault_localization-stop_on_fail1/test.desc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ main.c
77
line . function main$
88
^VERIFICATION FAILED$
99
--
10+
--
11+
--paths mode explores paths in a different order, finding a different failing
12+
assertion first, which changes the fault localization output.

regression/cbmc/outfile_no_dir/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE paths-lifo-expected-failure
1+
CORE
22
main.c
33
--dimacs --outfile /xyz/out.dimacs
44
^EXIT=1$

regression/cbmc/sat-solver-error/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-z3-smt-backend broken-cprover-smt-backend paths-lifo-expected-failure no-new-smt
1+
CORE broken-z3-smt-backend broken-cprover-smt-backend no-new-smt
22
test.c
33
--sat-solver non-existing-solver
44
^EXIT=1$

regression/cbmc/unreachable-goto2/test-vccs.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE paths-lifo-expected-failure
1+
CORE
22
test.c
33
--show-vcc --verbosity 8
44
^Generated 1 VCC\(s\), 1 remaining after simplification$

src/cbmc/cbmc_parse_options.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Daniel Kroening, kroening@kroening.com
1515
#include <util/exit_codes.h>
1616
#include <util/help_formatter.h>
1717
#include <util/invariant.h>
18+
#include <util/output_file.h>
1819
#include <util/unicode.h>
1920
#include <util/version.h>
2021

@@ -125,6 +126,7 @@ void cbmc_parse_optionst::set_default_analysis_flags(
125126
if(!options.is_set("unwinding-assertions"))
126127
{
127128
options.set_option("unwinding-assertions", enabled);
129+
options.set_option("paths-symex-explore-all", enabled);
128130
}
129131

130132
if(enabled)
@@ -670,6 +672,23 @@ int cbmc_parse_optionst::doit()
670672
if(
671673
options.get_bool_option("dimacs") || !options.get_option("outfile").empty())
672674
{
675+
// Validate outfile path early so that errors are reported even when
676+
// single-path symex simplifies away all VCCs (and thus never creates
677+
// the solver).
678+
const std::string outfile = options.get_option("outfile");
679+
if(!outfile.empty() && outfile != "-")
680+
{
681+
try
682+
{
683+
output_filet{outfile};
684+
}
685+
catch(const system_exceptiont &)
686+
{
687+
throw invalid_command_line_argument_exceptiont(
688+
"failed to open file: " + outfile, "--outfile");
689+
}
690+
}
691+
673692
if(options.get_bool_option("paths"))
674693
{
675694
stop_on_fail_verifiert<single_path_symex_checkert> verifier(

src/goto-checker/solver_factory.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,18 @@ smt2_dect::solvert solver_factoryt::get_smt2_solver_type() const
164164
return s;
165165
}
166166

167+
/// Check whether \p solver_name is a known SAT solver name. A solver may be
168+
/// known but not compiled in (in which case \ref get_sat_solver will fall back
169+
/// to the default solver with a warning).
170+
static bool is_known_sat_solver_name(const std::string &solver_name)
171+
{
172+
return solver_name == "zchaff" || solver_name == "booleforce" ||
173+
solver_name == "minisat1" || solver_name == "minisat2" ||
174+
solver_name == "ipasir" || solver_name == "picosat" ||
175+
solver_name == "lingeling" || solver_name == "glucose" ||
176+
solver_name == "cadical";
177+
}
178+
167179
/// Emit a warning for non-existent solver \p solver via \p message_handler.
168180
static void emit_solver_warning(
169181
message_handlert &message_handler,
@@ -314,6 +326,9 @@ get_sat_solver(message_handlert &message_handler, const optionst &options)
314326
}
315327
else
316328
{
329+
INVARIANT(
330+
!is_known_sat_solver_name(solver_option),
331+
"known solver names should be handled above");
317332
messaget log(message_handler);
318333
log.error() << "unknown solver '" << solver_option << "'"
319334
<< messaget::eom;
@@ -625,7 +640,16 @@ static void parse_sat_options(const cmdlinet &cmdline, optionst &options)
625640
options.set_option("dimacs", true);
626641

627642
if(cmdline.isset("sat-solver"))
628-
options.set_option("sat-solver", cmdline.get_value("sat-solver"));
643+
{
644+
const std::string solver = cmdline.get_value("sat-solver");
645+
options.set_option("sat-solver", solver);
646+
647+
if(!is_known_sat_solver_name(solver))
648+
{
649+
throw invalid_command_line_argument_exceptiont(
650+
"unknown solver '" + solver + "'", "--sat-solver");
651+
}
652+
}
629653
}
630654

631655
static void parse_smt2_options(const cmdlinet &cmdline, optionst &options)

0 commit comments

Comments
 (0)