Skip to content

Commit 5b525d6

Browse files
Assert that there is uncaught exception
That's the default behaviour because an escaping exception makes the JVM abort. The user can override this behaviour using the --no-uncaught-exception-check option.
1 parent 35777f2 commit 5b525d6

File tree

6 files changed

+62
-23
lines changed

6 files changed

+62
-23
lines changed

jbmc/regression/jbmc/catch1/test.desc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
CORE
22
catch1.class
33

4-
^EXIT=0$
4+
^EXIT=10$
55
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
6+
^VERIFICATION FAILED$
7+
^\[.*\] no uncaught exception: FAILURE$
78
--
89
^warning: ignoring
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
CORE
22
Test.class
33
--function Test.goo
4-
^EXIT=0$
4+
^EXIT=10$
55
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
6+
^VERIFICATION FAILED$
7+
no uncaught exception: FAILURE
78
--
89
^warning: ignoring

jbmc/src/java_bytecode/java_bytecode_instrument.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Date: June 2017
1919
#include <goto-programs/goto_functions.h>
2020

2121
#include "java_bytecode_convert_class.h"
22+
#include "java_entry_point.h"
2223
#include "java_utils.h"
2324

2425
class java_bytecode_instrumentt:public messaget
@@ -592,6 +593,30 @@ void java_bytecode_instrument_symbol(
592593
instrument(to_code(symbol.value));
593594
}
594595

596+
/// Instruments the start function with an assertion that checks whether
597+
/// an exception has escaped the entry point
598+
/// \param symbol_table: global symbol table
599+
void java_bytecode_instrument_uncaught_exceptions(symbol_tablet &symbol_table)
600+
{
601+
// retrieve the exception variable
602+
const symbolt &exc_symbol =
603+
symbol_table.lookup_ref(JAVA_ENTRY_POINT_EXCEPTION_SYMBOL);
604+
605+
symbolt &function =
606+
symbol_table.get_writeable_ref(goto_functionst::entry_point());
607+
codet &init_code = to_code(function.value);
608+
609+
// check that there is no uncaught exception
610+
code_assertt assert_no_exception;
611+
assert_no_exception.assertion() = equal_exprt(
612+
exc_symbol.symbol_expr(),
613+
null_pointer_exprt(to_pointer_type(exc_symbol.type)));
614+
source_locationt assert_location = function.location;
615+
assert_location.set_comment("no uncaught exception");
616+
assert_no_exception.add_source_location() = assert_location;
617+
init_code.move_to_operands(assert_no_exception);
618+
}
619+
595620
/// Instruments all the code in the symbol_table with
596621
/// runtime exceptions or corresponding assertions.
597622
/// Exceptions are thrown when the `throw_runtime_exceptions` flag is set.

jbmc/src/java_bytecode/java_bytecode_instrument.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ void java_bytecode_instrument(
2626
const bool throw_runtime_exceptions,
2727
message_handlert &_message_handler);
2828

29+
void java_bytecode_instrument_uncaught_exceptions(symbol_tablet &symbol_table);
30+
2931
extern const std::vector<std::string> exception_needed_classes;
3032

3133
#endif

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
4646
assume_inputs_non_null=cmd.isset("java-assume-inputs-non-null");
4747
string_refinement_enabled=cmd.isset("refine-strings");
4848
throw_runtime_exceptions=cmd.isset("java-throw-runtime-exceptions");
49+
assert_uncaught_exceptions = !cmd.isset("no-uncaught-exception-check");
50+
threading_support = cmd.isset("java-threading");
51+
4952
if(cmd.isset("java-max-input-array-length"))
5053
object_factory_parameters.max_nondet_array_length=
5154
std::stoi(cmd.get_value("java-max-input-array-length"));
@@ -69,14 +72,8 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
6972
else
7073
lazy_methods_mode=LAZY_METHODS_MODE_EAGER;
7174

72-
if(cmd.isset("java-threading"))
73-
threading_support = true;
74-
else
75-
threading_support = false;
76-
77-
if(cmd.isset("java-throw-runtime-exceptions"))
75+
if(throw_runtime_exceptions)
7876
{
79-
throw_runtime_exceptions = true;
8077
java_load_classes.insert(
8178
java_load_classes.end(),
8279
exception_needed_classes.begin(),
@@ -777,15 +774,23 @@ bool java_bytecode_languaget::generate_support_functions(
777774
convert_lazy_method(res.main_function.name, symbol_table);
778775

779776
// generate the test harness in __CPROVER__start and a call the entry point
780-
return
777+
if(
781778
java_entry_point(
782779
symbol_table,
783780
main_class,
784781
get_message_handler(),
785782
assume_inputs_non_null,
786783
object_factory_parameters,
787784
get_pointer_type_selector(),
788-
string_refinement_enabled);
785+
string_refinement_enabled))
786+
{
787+
return true;
788+
}
789+
790+
if(assert_uncaught_exceptions)
791+
java_bytecode_instrument_uncaught_exceptions(symbol_table);
792+
793+
return false;
789794
}
790795

791796
/// Uses a simple context-insensitive ('ci') analysis to determine which methods

jbmc/src/java_bytecode/java_bytecode_language.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,22 @@ Author: Daniel Kroening, [email protected]
2626

2727
#include <langapi/language.h>
2828

29-
#define JAVA_BYTECODE_LANGUAGE_OPTIONS /*NOLINT*/ \
30-
"(java-assume-inputs-non-null)" \
31-
"(java-throw-runtime-exceptions)" \
32-
"(java-max-input-array-length):" \
33-
"(java-max-input-tree-depth):" \
34-
"(java-max-vla-length):" \
35-
"(java-cp-include-files):" \
36-
"(lazy-methods)" \
37-
"(lazy-methods-extra-entry-point):" \
38-
"(java-load-class):" \
29+
// clang-format off
30+
#define JAVA_BYTECODE_LANGUAGE_OPTIONS /*NOLINT*/ \
31+
"(no-uncaught-exception-check)" \
32+
"(java-assume-inputs-non-null)" \
33+
"(java-throw-runtime-exceptions)" \
34+
"(java-max-input-array-length):" \
35+
"(java-max-input-tree-depth):" \
36+
"(java-max-vla-length):" \
37+
"(java-cp-include-files):" \
38+
"(lazy-methods)" \
39+
"(lazy-methods-extra-entry-point):" \
40+
"(java-load-class):" \
3941
"(java-no-load-class):"
4042

4143
#define JAVA_BYTECODE_LANGUAGE_OPTIONS_HELP /*NOLINT*/ \
44+
" --no-uncaught-exception-check ignore uncaught exceptions and errors\n" \
4245
" --java-assume-inputs-non-null never initialize reference-typed parameter to the\n" /* NOLINT(*) */ \
4346
" entry point with null\n" /* NOLINT(*) */ \
4447
" --java-throw-runtime-exceptions make implicit runtime exceptions explicit\n" /* NOLINT(*) */ \
@@ -55,6 +58,7 @@ Author: Daniel Kroening, [email protected]
5558
" treat METHODNAME as a possible program entry point for\n" /* NOLINT(*) */ \
5659
" the purpose of lazy method loading\n" /* NOLINT(*) */ \
5760
" A '.*' wildcard is allowed to specify all class members\n"
61+
// clang-format on
5862

5963
class symbolt;
6064

@@ -167,6 +171,7 @@ class java_bytecode_languaget:public languaget
167171
std::vector<irep_idt> lazy_methods_extra_entry_points;
168172
bool string_refinement_enabled;
169173
bool throw_runtime_exceptions;
174+
bool assert_uncaught_exceptions;
170175
java_string_library_preprocesst string_preprocess;
171176
std::string java_cp_include_files;
172177

0 commit comments

Comments
 (0)