Skip to content

Commit ec2933f

Browse files
committed
JBMC: run remove_exceptions after replace_java_nondet
The latter can introduce functions that need exception handlers, or more usually an ASSUME(@inflight_exception == null) guard against accidentally propagated exceptions. When replace_java_nondet is run after exception removal we can get odd behaviour, shown by the included test case, as the exception will be detected later than it should have been, or would escape from the ASSUME guard implied by a @MustNotThrow annotation.
1 parent f08e23b commit ec2933f

File tree

6 files changed

+53
-14
lines changed

6 files changed

+53
-14
lines changed
Binary file not shown.
Binary file not shown.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
public class JavaExceptionTest {
2+
3+
public static Fake getFake() {
4+
try {
5+
return org.cprover.CProver.nondetWithoutNull((Fake)null);
6+
}
7+
catch(Exception t) {
8+
// Should be reachable due to exception thrown in
9+
// nondet-initialize:
10+
return new Fake();
11+
}
12+
}
13+
14+
void test () {
15+
16+
Fake a = null;
17+
try {
18+
a = getFake();
19+
}
20+
catch(Exception t) {
21+
// Should be unreachable
22+
assert false;
23+
}
24+
25+
}
26+
27+
}
28+
29+
class Fake {
30+
protected final void cproverNondetInitialize() throws Exception {
31+
throw new Exception("Oh dear oh dear");
32+
}
33+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
JavaExceptionTest.class
3+
--function JavaExceptionTest.test
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -738,20 +738,6 @@ void jbmc_parse_optionst::process_goto_function(
738738
// Java virtual functions -> explicit dispatch tables:
739739
remove_virtual_functions(function);
740740

741-
if(using_symex_driven_loading)
742-
{
743-
// remove exceptions
744-
// If using symex-driven function loading we need to do this now so that
745-
// symex doesn't have to cope with exception-handling constructs; however
746-
// the results are slightly worse than running it in whole-program mode
747-
// (e.g. dead catch sites will be retained)
748-
remove_exceptions(
749-
goto_function.body,
750-
symbol_table,
751-
*class_hierarchy.get(),
752-
get_message_handler());
753-
}
754-
755741
auto function_is_stub = [&symbol_table, &model](const irep_idt &id) {
756742
return symbol_table.lookup_ref(id).value.is_nil() &&
757743
!model.can_produce_function(id);
@@ -768,6 +754,20 @@ void jbmc_parse_optionst::process_goto_function(
768754
object_factory_params,
769755
ID_java);
770756

757+
if(using_symex_driven_loading)
758+
{
759+
// remove exceptions
760+
// If using symex-driven function loading we need to do this now so that
761+
// symex doesn't have to cope with exception-handling constructs; however
762+
// the results are slightly worse than running it in whole-program mode
763+
// (e.g. dead catch sites will be retained)
764+
remove_exceptions(
765+
goto_function.body,
766+
symbol_table,
767+
*class_hierarchy.get(),
768+
get_message_handler());
769+
}
770+
771771
// add generic checks
772772
goto_check(ns, options, ID_java, function.get_goto_function());
773773

0 commit comments

Comments
 (0)