Skip to content

Commit caf3fdb

Browse files
Enable propagation of AssertionError
Introduces --propagate-assertion-error which allows to propgate AssertionError as performed in the JVM rather than using a goto ASSERT statement.
1 parent 5b525d6 commit caf3fdb

File tree

6 files changed

+57
-10
lines changed

6 files changed

+57
-10
lines changed

jbmc/src/janalyzer/janalyzer_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ bool janalyzer_parse_optionst::process_goto_program(const optionst &options)
670670
remove_virtual_functions(goto_model);
671671
// remove Java throw and catch
672672
// This introduces instanceof, so order is important:
673-
remove_exceptions(goto_model);
673+
remove_exceptions(goto_model, cmdline.isset("propagate-assertion-error"));
674674
// remove rtti
675675
remove_instanceof(goto_model);
676676

jbmc/src/java_bytecode/java_bytecode_language.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Author: Daniel Kroening, [email protected]
2929
// clang-format off
3030
#define JAVA_BYTECODE_LANGUAGE_OPTIONS /*NOLINT*/ \
3131
"(no-uncaught-exception-check)" \
32+
"(propagate-assertion-error)" \
3233
"(java-assume-inputs-non-null)" \
3334
"(java-throw-runtime-exceptions)" \
3435
"(java-max-input-array-length):" \
@@ -42,6 +43,7 @@ Author: Daniel Kroening, [email protected]
4243

4344
#define JAVA_BYTECODE_LANGUAGE_OPTIONS_HELP /*NOLINT*/ \
4445
" --no-uncaught-exception-check ignore uncaught exceptions and errors\n" \
46+
" --propagate-assertion-error propagate java.lang.AssertionError as exception\n" \
4547
" --java-assume-inputs-non-null never initialize reference-typed parameter to the\n" /* NOLINT(*) */ \
4648
" entry point with null\n" /* NOLINT(*) */ \
4749
" --java-throw-runtime-exceptions make implicit runtime exceptions explicit\n" /* NOLINT(*) */ \

jbmc/src/java_bytecode/remove_exceptions.cpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ class remove_exceptionst
8888
explicit remove_exceptionst(
8989
symbol_table_baset &_symbol_table,
9090
function_may_throwt _function_may_throw,
91+
bool propagate_assertion_error,
9192
bool remove_added_instanceof)
9293
: symbol_table(_symbol_table),
9394
function_may_throw(_function_may_throw),
95+
propagate_assertion_error(propagate_assertion_error),
9496
remove_added_instanceof(remove_added_instanceof)
9597
{
9698
}
@@ -101,6 +103,7 @@ class remove_exceptionst
101103
protected:
102104
symbol_table_baset &symbol_table;
103105
function_may_throwt function_may_throw;
106+
bool propagate_assertion_error;
104107
bool remove_added_instanceof;
105108

106109
symbol_exprt get_inflight_exception_global();
@@ -164,6 +167,9 @@ bool remove_exceptionst::function_or_callees_may_throw(
164167
{
165168
if(instr_it->is_throw())
166169
{
170+
if(propagate_assertion_error)
171+
return true;
172+
167173
const exprt &exc =
168174
uncaught_exceptions_domaint::get_exception_symbol(instr_it->code);
169175
bool is_assertion_error =
@@ -385,10 +391,10 @@ bool remove_exceptionst::instrument_throw(
385391
uncaught_exceptions_domaint::get_exception_type(exc_expr.type())).
386392
find("java.lang.AssertionError")!=std::string::npos;
387393

388-
// we don't count AssertionError (we couldn't catch it anyway
389-
// and this may reduce the instrumentation considerably if the programmer
390-
// used assertions)
391-
if(assertion_error)
394+
// we allow AssertionError not to be propagated since
395+
// this may reduce the instrumentation considerably if the programmer
396+
// used assertions
397+
if(assertion_error && !propagate_assertion_error)
392398
return false;
393399

394400
add_exception_dispatch_sequence(
@@ -472,7 +478,21 @@ void remove_exceptionst::instrument_exceptions(
472478

473479
Forall_goto_program_instructions(instr_it, goto_program)
474480
{
475-
if(instr_it->is_decl())
481+
if(instr_it->is_assert())
482+
{
483+
if(propagate_assertion_error)
484+
{
485+
// suppress user-provided assertion
486+
// because we propgate the AssertionError
487+
if(
488+
instr_it->guard.is_false() &&
489+
instr_it->source_location.get_bool("user-provided"))
490+
{
491+
instr_it->make_skip();
492+
}
493+
}
494+
}
495+
else if(instr_it->is_decl())
476496
{
477497
code_declt decl=to_code_decl(instr_it->code);
478498
locals.push_back(decl.symbol());
@@ -580,6 +600,7 @@ void remove_exceptionst::operator()(goto_programt &goto_program)
580600
void remove_exceptions(
581601
symbol_table_baset &symbol_table,
582602
goto_functionst &goto_functions,
603+
bool propagate_assertion_error,
583604
remove_exceptions_typest type)
584605
{
585606
const namespacet ns(symbol_table);
@@ -592,6 +613,7 @@ void remove_exceptions(
592613
remove_exceptionst remove_exceptions(
593614
symbol_table,
594615
function_may_throw,
616+
propagate_assertion_error,
595617
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
596618
remove_exceptions(goto_functions);
597619
}
@@ -612,6 +634,7 @@ void remove_exceptions(
612634
void remove_exceptions(
613635
goto_programt &goto_program,
614636
symbol_table_baset &symbol_table,
637+
bool propagate_assertion_error,
615638
remove_exceptions_typest type)
616639
{
617640
remove_exceptionst::function_may_throwt any_function_may_throw =
@@ -620,12 +643,20 @@ void remove_exceptions(
620643
remove_exceptionst remove_exceptions(
621644
symbol_table,
622645
any_function_may_throw,
646+
propagate_assertion_error,
623647
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
624648
remove_exceptions(goto_program);
625649
}
626650

627651
/// removes throws/CATCH-POP/CATCH-PUSH
628-
void remove_exceptions(goto_modelt &goto_model, remove_exceptions_typest type)
652+
void remove_exceptions(
653+
goto_modelt &goto_model,
654+
bool propagate_assertion_error,
655+
remove_exceptions_typest type)
629656
{
630-
remove_exceptions(goto_model.symbol_table, goto_model.goto_functions, type);
657+
remove_exceptions(
658+
goto_model.symbol_table,
659+
goto_model.goto_functions,
660+
propagate_assertion_error,
661+
type);
631662
}

jbmc/src/java_bytecode/remove_exceptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ enum class remove_exceptions_typest
3232
void remove_exceptions(
3333
goto_programt &goto_program,
3434
symbol_table_baset &symbol_table,
35+
bool propagate_assertion_error,
3536
remove_exceptions_typest type =
3637
remove_exceptions_typest::DONT_REMOVE_INSTANCEOF);
3738

3839
void remove_exceptions(
3940
goto_modelt &goto_model,
41+
bool propagate_assertion_error,
4042
remove_exceptions_typest type =
4143
remove_exceptions_typest::DONT_REMOVE_INSTANCEOF);
4244

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,11 @@ void jbmc_parse_optionst::get_command_line_options(optionst &options)
382382

383383
PARSE_OPTIONS_GOTO_TRACE(cmdline, options);
384384

385+
if(cmdline.isset("propagate-assertion-error"))
386+
options.set_option("propagate-assertion-error", true);
387+
else
388+
options.set_option("propagate-assertion-error", false);
389+
385390
if(cmdline.isset("symex-driven-lazy-loading"))
386391
{
387392
options.set_option("symex-driven-lazy-loading", true);
@@ -743,6 +748,8 @@ void jbmc_parse_optionst::process_goto_function(
743748

744749
bool using_symex_driven_loading =
745750
options.get_bool_option("symex-driven-lazy-loading");
751+
bool propagate_assertion_error =
752+
options.get_bool_option("propagate-assertion-error");
746753

747754
try
748755
{
@@ -761,6 +768,7 @@ void jbmc_parse_optionst::process_goto_function(
761768
remove_exceptions(
762769
goto_function.body,
763770
symbol_table,
771+
propagate_assertion_error,
764772
remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
765773
}
766774

@@ -899,6 +907,8 @@ bool jbmc_parse_optionst::process_goto_functions(
899907

900908
bool using_symex_driven_loading =
901909
options.get_bool_option("symex-driven-lazy-loading");
910+
bool propagate_assertion_error =
911+
options.get_bool_option("propagate-assertion-error");
902912

903913
// When using symex-driven lazy loading, *all* relevant processing is done
904914
// during process_goto_function, so we have nothing to do here.
@@ -908,7 +918,9 @@ bool jbmc_parse_optionst::process_goto_functions(
908918
// remove catch and throw
909919
// (introduces instanceof but request it is removed)
910920
remove_exceptions(
911-
goto_model, remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
921+
goto_model,
922+
propagate_assertion_error,
923+
remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
912924

913925
// instrument library preconditions
914926
instrument_preconditions(goto_model);

jbmc/src/jdiff/jdiff_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ bool jdiff_parse_optionst::process_goto_program(
346346
// Java virtual functions -> explicit dispatch tables:
347347
remove_virtual_functions(goto_model);
348348
// remove catch and throw
349-
remove_exceptions(goto_model);
349+
remove_exceptions(goto_model, cmdline.isset("propagate-assertion-error"));
350350
// Java instanceof -> clsid comparison:
351351
remove_instanceof(goto_model);
352352

0 commit comments

Comments
 (0)