Skip to content

Commit 22f3a00

Browse files
authored
Merge pull request #1196 from smowton/smowton/fix/exception_catch
Implement exception catching
2 parents 9e10715 + 9a1289d commit 22f3a00

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+706
-338
lines changed
643 Bytes
Binary file not shown.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
VERIFICATION SUCCESSFUL
7+
--
8+
^warning: ignoring
9+
--
10+
This test checks that a thrown exception is caught, and is not erroneously rethrown
11+
on function exit such that another surrounding try block can catch it again.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
public class test {
2+
public static void main () {
3+
try {
4+
f();
5+
}
6+
catch(Exception e) {
7+
assert(false); // Should be unreachable
8+
}
9+
}
10+
11+
public static void f() {
12+
try {
13+
throw new Exception();
14+
}
15+
catch(Exception e) {
16+
// Should prevent main's catch handler from being invoked
17+
}
18+
}
19+
}
20+
594 Bytes
Binary file not shown.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file test\.java line 7 function java::test\.main:\(\)V bytecode-index 9: FAILURE
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class test {
2+
public static void main() throws Exception {
3+
try {
4+
throw new Exception();
5+
}
6+
finally {
7+
assert(false);
8+
}
9+
}
10+
}
11+
637 Bytes
Binary file not shown.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file test\.java line 8 function java::test\.main:\(\)V bytecode-index 9: FAILURE
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public class test {
2+
public static void main() throws Exception {
3+
try {
4+
throw new Exception();
5+
}
6+
catch(Exception e) { }
7+
finally {
8+
assert(false);
9+
}
10+
}
11+
}
12+
727 Bytes
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file test\.java line 7 function java::test\.main:\(\)V bytecode-index 9: SUCCESS
7+
assertion at file test\.java line 10 function java::test\.main:\(\)V bytecode-index 22: FAILURE
8+
^VERIFICATION FAILED$
9+
--
10+
^warning: ignoring
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
public class test {
2+
public static void main() throws Exception {
3+
try {
4+
throw new NullPointerException();
5+
}
6+
catch(ArithmeticException e) {
7+
assert(false);
8+
}
9+
finally {
10+
assert(false);
11+
}
12+
}
13+
}
14+
713 Bytes
Binary file not shown.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file test\.java line 11 function java::test\.main:\(\)V bytecode-index 7: FAILURE
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
public class test {
2+
public static void main() throws Exception {
3+
try {
4+
int x = 1;
5+
x++;
6+
}
7+
catch(ArithmeticException e) {
8+
assert(false);
9+
}
10+
finally {
11+
assert(false);
12+
}
13+
}
14+
}
15+
681 Bytes
Binary file not shown.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file test\.java line 7 function java::test\.main:\(\)V bytecode-index 12: FAILURE
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
public class test {
2+
public static void main() throws Exception {
3+
try {
4+
f();
5+
}
6+
finally {
7+
assert(false);
8+
}
9+
}
10+
11+
public static void f() throws Exception {
12+
throw new Exception();
13+
}
14+
}
15+
720 Bytes
Binary file not shown.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file test\.java line 8 function java::test\.main:\(\)V bytecode-index 12: FAILURE
7+
^VERIFICATION FAILED$
8+
--
9+
^warning: ignoring
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
public class test {
2+
public static void main() throws Exception {
3+
try {
4+
f();
5+
}
6+
catch(Exception e) { }
7+
finally {
8+
assert(false);
9+
}
10+
}
11+
12+
public static void f() throws Exception {
13+
throw new Exception();
14+
}
15+
}
16+
818 Bytes
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file test\.java line 7 function java::test\.main:\(\)V bytecode-index 12: SUCCESS
7+
assertion at file test\.java line 10 function java::test\.main:\(\)V bytecode-index 25: FAILURE
8+
^VERIFICATION FAILED$
9+
--
10+
^warning: ignoring
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
public class test {
2+
public static void main() throws Exception {
3+
try {
4+
f();
5+
}
6+
catch(ArithmeticException e) {
7+
assert(false);
8+
}
9+
finally {
10+
assert(false);
11+
}
12+
}
13+
14+
public static void f() throws NullPointerException {
15+
throw new NullPointerException();
16+
}
17+
}
18+

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ bool cbmc_parse_optionst::process_goto_program(
815815
cmdline.isset("pointer-check"));
816816
// Java virtual functions -> explicit dispatch tables:
817817
remove_virtual_functions(symbol_table, goto_functions);
818-
// remove catch and throw
818+
// remove catch and throw (introduces instanceof)
819819
remove_exceptions(symbol_table, goto_functions);
820820
// Similar removal of RTTI inspection:
821821
remove_instanceof(symbol_table, goto_functions);

src/goto-analyzer/goto_analyzer_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ bool goto_analyzer_parse_optionst::process_goto_program(
356356
// Java virtual functions -> explicit dispatch tables:
357357
remove_virtual_functions(goto_model);
358358
// remove Java throw and catch
359+
// This introduces instanceof, so order is important:
359360
remove_exceptions(goto_model);
360361
// remove rtti
361362
remove_instanceof(goto_model);

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ void goto_instrument_parse_optionst::do_indirect_call_and_rtti_removal(
806806
status() << "Virtual function removal" << eom;
807807
remove_virtual_functions(symbol_table, goto_functions);
808808
status() << "Catch and throw removal" << eom;
809+
// This introduces instanceof, so order is important:
809810
remove_exceptions(symbol_table, goto_functions);
810811
status() << "Java instanceof removal" << eom;
811812
remove_instanceof(symbol_table, goto_functions);

src/goto-programs/goto_convert.cpp

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,31 +58,24 @@ static void finish_catch_push_targets(goto_programt &dest)
5858
// in the second pass set the targets
5959
Forall_goto_program_instructions(it, dest)
6060
{
61-
if(it->is_catch())
61+
if(it->is_catch() && it->code.get_statement()==ID_push_catch)
6262
{
63-
bool handler_added=true;
64-
irept exceptions=it->code.find(ID_exception_list);
63+
// Populate `targets` with a GOTO instruction target per
64+
// exception handler if it isn't already populated.
65+
// (Java handlers, for example, need this finish step; C++
66+
// handlers will already be populated by now)
6567

66-
if(exceptions.is_nil() &&
67-
it->code.has_operands())
68-
exceptions=it->code.op0().find(ID_exception_list);
69-
70-
const irept::subt &exception_list=exceptions.get_sub();
71-
72-
if(!exception_list.empty())
68+
if(it->targets.empty())
7369
{
74-
// in this case we have a CATCH_PUSH
75-
irept handlers=it->code.find(ID_label);
76-
if(handlers.is_nil() &&
77-
it->code.has_operands())
78-
handlers=it->code.op0().find(ID_label);
79-
const irept::subt &handler_list=handlers.get_sub();
80-
81-
// some handlers may not have been converted (if there was no
82-
// exception to be caught); in such a situation we abort
70+
bool handler_added=true;
71+
const code_push_catcht::exception_listt &handler_list=
72+
to_code_push_catch(it->code).exception_list();
73+
8374
for(const auto &handler : handler_list)
8475
{
85-
if(label_targets.find(handler.id())==label_targets.end())
76+
// some handlers may not have been converted (if there was no
77+
// exception to be caught); in such a situation we abort
78+
if(label_targets.find(handler.get_label())==label_targets.end())
8679
{
8780
handler_added=false;
8881
break;
@@ -93,14 +86,7 @@ static void finish_catch_push_targets(goto_programt &dest)
9386
continue;
9487

9588
for(const auto &handler : handler_list)
96-
{
97-
std::map<irep_idt,
98-
goto_programt::targett>::const_iterator handler_it=
99-
label_targets.find(handler.id());
100-
assert(handler_it!=label_targets.end());
101-
// set the target
102-
it->targets.push_back(handler_it->second);
103-
}
89+
it->targets.push_back(label_targets.at(handler.get_label()));
10490
}
10591
}
10692
}
@@ -566,6 +552,10 @@ void goto_convertt::convert(
566552
forall_operands(it, code)
567553
convert(to_code(*it), dest);
568554
}
555+
else if(statement==ID_push_catch ||
556+
statement==ID_pop_catch ||
557+
statement==ID_exception_landingpad)
558+
copy(code, CATCH, dest);
569559
else
570560
copy(code, OTHER, dest);
571561

src/goto-programs/goto_convert_class.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,6 @@ class goto_convertt:public messaget
9797
side_effect_exprt &expr,
9898
goto_programt &dest,
9999
bool result_is_used);
100-
void remove_push_catch(
101-
side_effect_exprt &expr,
102-
goto_programt &dest);
103100
void remove_assignment(
104101
side_effect_exprt &expr,
105102
goto_programt &dest,
@@ -243,7 +240,6 @@ class goto_convertt:public messaget
243240
void convert_msc_try_except(const codet &code, goto_programt &dest);
244241
void convert_msc_leave(const codet &code, goto_programt &dest);
245242
void convert_try_catch(const codet &code, goto_programt &dest);
246-
void convert_java_try_catch(const codet &code, goto_programt &dest);
247243
void convert_CPROVER_try_catch(const codet &code, goto_programt &dest);
248244
void convert_CPROVER_try_finally(const codet &code, goto_programt &dest);
249245
void convert_CPROVER_throw(const codet &code, goto_programt &dest);

0 commit comments

Comments
 (0)