Skip to content

Commit d2fd7da

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 2aaeb65 commit d2fd7da

File tree

6 files changed

+57
-10
lines changed

6 files changed

+57
-10
lines changed

jbmc/src/janalyzer/janalyzer_parse_options.cpp

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

jbmc/src/java_bytecode/java_bytecode_language.h

+2
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
"(no-core-models)" \
3334
"(java-assume-inputs-non-null)" \
3435
"(java-throw-runtime-exceptions)" \
@@ -43,6 +44,7 @@ Author: Daniel Kroening, [email protected]
4344

4445
#define JAVA_BYTECODE_LANGUAGE_OPTIONS_HELP /*NOLINT*/ \
4546
" --no-uncaught-exception-check ignore uncaught exceptions and errors\n" \
47+
" --propagate-assertion-error propagate java.lang.AssertionError\n" \
4648
" --no-core-models don't load internally provided models for core classes in\n"/* NOLINT(*) */ \
4749
" the Java Class Library\n" /* NOLINT(*) */ \
4850
" --java-assume-inputs-non-null never initialize reference-typed parameter to the\n" /* NOLINT(*) */ \

jbmc/src/java_bytecode/remove_exceptions.cpp

+38-7
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ class remove_exceptionst
8686
explicit remove_exceptionst(
8787
symbol_table_baset &_symbol_table,
8888
function_may_throwt _function_may_throw,
89+
bool propagate_assertion_error,
8990
bool remove_added_instanceof)
9091
: symbol_table(_symbol_table),
9192
function_may_throw(_function_may_throw),
93+
propagate_assertion_error(propagate_assertion_error),
9294
remove_added_instanceof(remove_added_instanceof)
9395
{
9496
}
@@ -99,6 +101,7 @@ class remove_exceptionst
99101
protected:
100102
symbol_table_baset &symbol_table;
101103
function_may_throwt function_may_throw;
104+
bool propagate_assertion_error;
102105
bool remove_added_instanceof;
103106

104107
symbol_exprt get_inflight_exception_global();
@@ -162,6 +165,9 @@ bool remove_exceptionst::function_or_callees_may_throw(
162165
{
163166
if(instr_it->is_throw())
164167
{
168+
if(propagate_assertion_error)
169+
return true;
170+
165171
const exprt &exc =
166172
uncaught_exceptions_domaint::get_exception_symbol(instr_it->code);
167173
bool is_assertion_error =
@@ -383,10 +389,10 @@ void remove_exceptionst::instrument_throw(
383389
uncaught_exceptions_domaint::get_exception_type(exc_expr.type())).
384390
find("java.lang.AssertionError")!=std::string::npos;
385391

386-
// we don't count AssertionError (we couldn't catch it anyway
387-
// and this may reduce the instrumentation considerably if the programmer
388-
// used assertions)
389-
if(assertion_error)
392+
// we allow AssertionError not to be propgated since
393+
// this may reduce the instrumentation considerably if the programmer
394+
// used assertions
395+
if(assertion_error && !propagate_assertion_error)
390396
return;
391397

392398
add_exception_dispatch_sequence(
@@ -462,7 +468,21 @@ void remove_exceptionst::instrument_exceptions(
462468

463469
Forall_goto_program_instructions(instr_it, goto_program)
464470
{
465-
if(instr_it->is_decl())
471+
if(instr_it->is_assert())
472+
{
473+
if(propagate_assertion_error)
474+
{
475+
// suppress user-provided assertion
476+
// because we propgate the AssertionError
477+
if(
478+
instr_it->guard.is_false() &&
479+
instr_it->source_location.get_bool("user-provided"))
480+
{
481+
instr_it->make_skip();
482+
}
483+
}
484+
}
485+
else if(instr_it->is_decl())
466486
{
467487
code_declt decl=to_code_decl(instr_it->code);
468488
locals.push_back(decl.symbol());
@@ -566,6 +586,7 @@ void remove_exceptionst::operator()(goto_programt &goto_program)
566586
void remove_exceptions(
567587
symbol_table_baset &symbol_table,
568588
goto_functionst &goto_functions,
589+
bool propagate_assertion_error,
569590
remove_exceptions_typest type)
570591
{
571592
const namespacet ns(symbol_table);
@@ -578,6 +599,7 @@ void remove_exceptions(
578599
remove_exceptionst remove_exceptions(
579600
symbol_table,
580601
function_may_throw,
602+
propagate_assertion_error,
581603
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
582604
remove_exceptions(goto_functions);
583605
}
@@ -598,6 +620,7 @@ void remove_exceptions(
598620
void remove_exceptions(
599621
goto_programt &goto_program,
600622
symbol_table_baset &symbol_table,
623+
bool propagate_assertion_error,
601624
remove_exceptions_typest type)
602625
{
603626
remove_exceptionst::function_may_throwt any_function_may_throw =
@@ -606,12 +629,20 @@ void remove_exceptions(
606629
remove_exceptionst remove_exceptions(
607630
symbol_table,
608631
any_function_may_throw,
632+
propagate_assertion_error,
609633
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
610634
remove_exceptions(goto_program);
611635
}
612636

613637
/// removes throws/CATCH-POP/CATCH-PUSH
614-
void remove_exceptions(goto_modelt &goto_model, remove_exceptions_typest type)
638+
void remove_exceptions(
639+
goto_modelt &goto_model,
640+
bool propagate_assertion_error,
641+
remove_exceptions_typest type)
615642
{
616-
remove_exceptions(goto_model.symbol_table, goto_model.goto_functions, type);
643+
remove_exceptions(
644+
goto_model.symbol_table,
645+
goto_model.goto_functions,
646+
propagate_assertion_error,
647+
type);
617648
}

jbmc/src/java_bytecode/remove_exceptions.h

+2
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

+13-1
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ void jbmc_parse_optionst::get_command_line_options(optionst &options)
377377

378378
PARSE_OPTIONS_GOTO_TRACE(cmdline, options);
379379

380+
if(cmdline.isset("propagate-assertion-error"))
381+
options.set_option("propagate-assertion-error", true);
382+
else
383+
options.set_option("propagate-assertion-error", false);
384+
380385
if(cmdline.isset("symex-driven-lazy-loading"))
381386
{
382387
options.set_option("symex-driven-lazy-loading", true);
@@ -738,6 +743,8 @@ void jbmc_parse_optionst::process_goto_function(
738743

739744
bool using_symex_driven_loading =
740745
options.get_bool_option("symex-driven-lazy-loading");
746+
bool propagate_assertion_error =
747+
options.get_bool_option("propagate-assertion-error");
741748

742749
try
743750
{
@@ -756,6 +763,7 @@ void jbmc_parse_optionst::process_goto_function(
756763
remove_exceptions(
757764
goto_function.body,
758765
symbol_table,
766+
propagate_assertion_error,
759767
remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
760768
}
761769

@@ -894,6 +902,8 @@ bool jbmc_parse_optionst::process_goto_functions(
894902

895903
bool using_symex_driven_loading =
896904
options.get_bool_option("symex-driven-lazy-loading");
905+
bool propagate_assertion_error =
906+
options.get_bool_option("propagate-assertion-error");
897907

898908
// When using symex-driven lazy loading, *all* relevant processing is done
899909
// during process_goto_function, so we have nothing to do here.
@@ -903,7 +913,9 @@ bool jbmc_parse_optionst::process_goto_functions(
903913
// remove catch and throw
904914
// (introduces instanceof but request it is removed)
905915
remove_exceptions(
906-
goto_model, remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
916+
goto_model,
917+
propagate_assertion_error,
918+
remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
907919

908920
// instrument library preconditions
909921
instrument_preconditions(goto_model);

jbmc/src/jdiff/jdiff_parse_options.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ bool jdiff_parse_optionst::process_goto_program(
349349
// Java virtual functions -> explicit dispatch tables:
350350
remove_virtual_functions(goto_model);
351351
// remove catch and throw
352-
remove_exceptions(goto_model);
352+
remove_exceptions(goto_model, cmdline.isset("propagate-assertion-error"));
353353
// Java instanceof -> clsid comparison:
354354
remove_instanceof(goto_model);
355355

0 commit comments

Comments
 (0)