Skip to content

Commit 04c0205

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 --disable-uncaught-exception-check option.
1 parent 55bdbc7 commit 04c0205

9 files changed

+87
-32
lines changed

jbmc/regression/jbmc/catch1/test.desc

+3-2
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
catch1.class
3+
--disable-uncaught-exception-check
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
+3-2
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

+22
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,27 @@ 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 init_code: the code block to which the assertion is appended
599+
/// \param exc_symbol: the top-level exception symbol
600+
/// \param source_location: the source location to attach to the assertion
601+
void java_bytecode_instrument_uncaught_exceptions(
602+
codet &init_code,
603+
const symbolt &exc_symbol,
604+
const source_locationt &source_location)
605+
{
606+
// check that there is no uncaught exception
607+
code_assertt assert_no_exception;
608+
assert_no_exception.assertion() = equal_exprt(
609+
exc_symbol.symbol_expr(),
610+
null_pointer_exprt(to_pointer_type(exc_symbol.type)));
611+
source_locationt assert_location = source_location;
612+
assert_location.set_comment("no uncaught exception");
613+
assert_no_exception.add_source_location() = assert_location;
614+
init_code.move_to_operands(assert_no_exception);
615+
}
616+
595617
/// Instruments all the code in the symbol_table with
596618
/// runtime exceptions or corresponding assertions.
597619
/// Exceptions are thrown when the `throw_runtime_exceptions` flag is set.

jbmc/src/java_bytecode/java_bytecode_instrument.h

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Date: June 2017
1515
#include <util/message.h>
1616
#include <util/irep.h>
1717

18+
class codet;
19+
1820
void java_bytecode_instrument_symbol(
1921
symbol_table_baset &symbol_table,
2022
symbolt &symbol,
@@ -26,6 +28,11 @@ void java_bytecode_instrument(
2628
const bool throw_runtime_exceptions,
2729
message_handlert &_message_handler);
2830

31+
void java_bytecode_instrument_uncaught_exceptions(
32+
codet &init_code,
33+
const symbolt &exc_symbol,
34+
const source_locationt &source_location);
35+
2936
extern const std::vector<std::string> exception_needed_classes;
3037

3138
#endif

jbmc/src/java_bytecode/java_bytecode_language.cpp

+13-16
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("disable-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,15 @@ 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
781-
java_entry_point(
782-
symbol_table,
783-
main_class,
784-
get_message_handler(),
785-
assume_inputs_non_null,
786-
object_factory_parameters,
787-
get_pointer_type_selector(),
788-
string_refinement_enabled);
777+
return java_entry_point(
778+
symbol_table,
779+
main_class,
780+
get_message_handler(),
781+
assume_inputs_non_null,
782+
assert_uncaught_exceptions,
783+
object_factory_parameters,
784+
get_pointer_type_selector(),
785+
string_refinement_enabled);
789786
}
790787

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

jbmc/src/java_bytecode/java_bytecode_language.h

+16-10
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,23 @@ 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+
"(disable-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+
" --disable-uncaught-exception-check" \
45+
" ignore uncaught exceptions and errors\n" \
4246
" --java-assume-inputs-non-null never initialize reference-typed parameter to the\n" /* NOLINT(*) */ \
4347
" entry point with null\n" /* NOLINT(*) */ \
4448
" --java-throw-runtime-exceptions make implicit runtime exceptions explicit\n" /* NOLINT(*) */ \
@@ -55,6 +59,7 @@ Author: Daniel Kroening, [email protected]
5559
" treat METHODNAME as a possible program entry point for\n" /* NOLINT(*) */ \
5660
" the purpose of lazy method loading\n" /* NOLINT(*) */ \
5761
" A '.*' wildcard is allowed to specify all class members\n"
62+
// clang-format on
5863

5964
class symbolt;
6065

@@ -167,6 +172,7 @@ class java_bytecode_languaget:public languaget
167172
std::vector<irep_idt> lazy_methods_extra_entry_points;
168173
bool string_refinement_enabled;
169174
bool throw_runtime_exceptions;
175+
bool assert_uncaught_exceptions;
170176
java_string_library_preprocesst string_preprocess;
171177
std::string java_cp_include_files;
172178

jbmc/src/java_bytecode/java_entry_point.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Author: Daniel Kroening, [email protected]
1818

1919
#include <linking/static_lifetime_init.h>
2020

21+
#include "java_bytecode_instrument.h"
2122
#include "java_object_factory.h"
2223
#include "java_string_literals.h"
2324
#include "java_utils.h"
@@ -520,6 +521,7 @@ bool java_entry_point(
520521
const irep_idt &main_class,
521522
message_handlert &message_handler,
522523
bool assume_init_pointers_not_null,
524+
bool assert_uncaught_exceptions,
523525
const object_factory_parameterst &object_factory_parameters,
524526
const select_pointer_typet &pointer_type_selector,
525527
bool string_refinement_enabled)
@@ -554,6 +556,7 @@ bool java_entry_point(
554556
symbol_table,
555557
message_handler,
556558
assume_init_pointers_not_null,
559+
assert_uncaught_exceptions,
557560
object_factory_parameters,
558561
pointer_type_selector);
559562
}
@@ -576,7 +579,8 @@ bool generate_java_start_function(
576579
symbol_table_baset &symbol_table,
577580
message_handlert &message_handler,
578581
bool assume_init_pointers_not_null,
579-
const object_factory_parameterst& object_factory_parameters,
582+
bool assert_uncaught_exceptions,
583+
const object_factory_parameterst &object_factory_parameters,
580584
const select_pointer_typet &pointer_type_selector)
581585
{
582586
messaget message(message_handler);
@@ -699,6 +703,13 @@ bool generate_java_start_function(
699703
// declare certain (which?) variables as test outputs
700704
java_record_outputs(symbol, main_arguments, init_code, symbol_table);
701705

706+
// add uncaught-exception check if requested
707+
if(assert_uncaught_exceptions)
708+
{
709+
java_bytecode_instrument_uncaught_exceptions(
710+
init_code, exc_symbol, symbol.location);
711+
}
712+
702713
// create a symbol for the __CPROVER__start function, associate the code that
703714
// we just built and register it in the symbol table
704715
symbolt new_symbol;

jbmc/src/java_bytecode/java_entry_point.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ bool java_entry_point(
2424
const irep_idt &main_class,
2525
class message_handlert &message_handler,
2626
bool assume_init_pointers_not_null,
27+
bool assert_uncaught_exceptions,
2728
const object_factory_parameterst &object_factory_parameters,
2829
const select_pointer_typet &pointer_type_selector,
2930
bool string_refinement_enabled);
@@ -74,7 +75,8 @@ bool generate_java_start_function(
7475
class symbol_table_baset &symbol_table,
7576
class message_handlert &message_handler,
7677
bool assume_init_pointers_not_null,
77-
const object_factory_parameterst& object_factory_parameters,
78+
bool assert_uncaught_exceptions,
79+
const object_factory_parameterst &object_factory_parameters,
7880
const select_pointer_typet &pointer_type_selector);
7981

8082
#endif // CPROVER_JAVA_BYTECODE_JAVA_ENTRY_POINT_H

0 commit comments

Comments
 (0)