Skip to content

Commit 60c7c8c

Browse files
Address reviewers comments
1 parent e960c50 commit 60c7c8c

13 files changed

+155
-118
lines changed

regression/cbmc-java/ArrayIndexOutOfBoundsException/ArrayIndexOutOfBoundsException.java

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
public class ArrayIndexOutOfBoundsExceptionTest {
2+
public static void main(String args[]) {
3+
try {
4+
int[] a=new int[4];
5+
a[6]=0;
6+
// TODO: fix the bytecode convertion such that there is no need for
7+
// an explicit throw in order to convert the handler
8+
throw new RuntimeException();
9+
}
10+
catch(ArrayIndexOutOfBoundsException exc) {
11+
assert false;
12+
}
13+
}
14+
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
CORE
2-
ArrayIndexOutOfBoundsException.class
2+
ArrayIndexOutOfBoundsExceptionTest.class
33
--java-throw-runtime-exceptions
4-
^EXIT=0$
4+
^EXIT=10$
55
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
6+
^.*assertion at file ArrayIndexOutOfBoundsExceptionTest.java line 11 function.*: FAILURE$
7+
^VERIFICATION FAILED$
78
--
89
^warning: ignoring
Binary file not shown.

regression/cbmc-java/NegativeArraySizeException/NegativeArraySizeException.java

Lines changed: 0 additions & 5 deletions
This file was deleted.
Binary file not shown.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class NegativeArraySizeExceptionTest {
2+
public static void main(String args[]) {
3+
try {
4+
int a[]=new int[-1];
5+
throw new RuntimeException();
6+
}
7+
catch (NegativeArraySizeException exc) {
8+
assert false;
9+
}
10+
}
11+
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
CORE
2-
NegativeArraySizeException.class
2+
NegativeArraySizeExceptionTest.class
33
--java-throw-runtime-exceptions
4-
^EXIT=0$
4+
^EXIT=10$
55
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
6+
^.*assertion at file NegativeArraySizeExceptionTest.java line 8 function.*: FAILURE$
7+
^VERIFICATION FAILED$
78
--
89
^warning: ignoring

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,7 @@ void cbmc_parse_optionst::help()
11661166
// NOLINTNEXTLINE(whitespace/line_length)
11671167
" --java-max-vla-length limit the length of user-code-created arrays\n"
11681168
// NOLINTNEXTLINE(whitespace/line_length)
1169+
" --java-throw-runtime-exceptions Throw runtime exceptions when necessary"
11691170
" --java-cp-include-files regexp or JSON list of files to load (with '@' prefix)\n"
11701171
" --java-unwind-enum-static try to unwind loops in static initialization of enums\n"
11711172
"\n"

src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 114 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Author: Daniel Kroening, [email protected]
2525
#include "java_bytecode_convert_method.h"
2626
#include "java_bytecode_convert_method_class.h"
2727
#include "bytecode_info.h"
28+
#include "java_object_factory.h"
29+
#include "java_root_class.h"
2830
#include "java_types.h"
2931

3032
#include <limits>
@@ -569,53 +571,105 @@ codet java_bytecode_convert_methodt::get_array_bounds_check(
569571

570572
/*******************************************************************\
571573
572-
Function: throw_array_access_exception
574+
Function: throw_exception
573575
574576
Inputs:
575577
576578
Outputs:
577579
578-
Purpose: Checks whether the array access array_struct[idx]
579-
is out-of-bounds, and throws ArrayIndexOutofBoundsException
580-
if necessary
580+
Purpose: Creates a class stub for exc_name and generates a
581+
conditional GOTO such that exc_name is thrown when
582+
cond is met
581583
582584
\*******************************************************************/
583585

584-
codet java_bytecode_convert_methodt::throw_array_access_exception(
585-
const exprt &array_struct,
586-
const exprt &idx,
587-
const source_locationt &original_loc)
586+
codet java_bytecode_convert_methodt::throw_exception(
587+
const exprt &cond,
588+
const source_locationt &original_loc,
589+
const irep_idt &exc_name)
588590
{
589-
symbolt exc_symbol;
590-
if(!symbol_table.has_symbol("ArrayIndexOutOfBoundsException"))
591+
exprt exc;
592+
code_blockt init_code;
593+
const irep_idt &exc_obj_name=id2string(goto_functionst::entry_point())+
594+
"::"+id2string(exc_name);
595+
596+
if(!symbol_table.has_symbol(exc_obj_name))
591597
{
592-
exc_symbol.is_static_lifetime=true;
593-
exc_symbol.base_name="ArrayIndexOutOfBoundsException";
594-
exc_symbol.name="ArrayIndexOutOfBoundsException";
598+
// for now, create a class stub
599+
// TODO: model exceptions and use that model
600+
class_typet class_type;
601+
class_type.set_tag(exc_name);
602+
class_type.set(ID_base_name, exc_name);
603+
class_type.set(ID_incomplete_class, true);
604+
605+
// produce class symbol
606+
symbolt exc_symbol;
607+
exc_symbol.base_name=exc_name;
608+
exc_symbol.pretty_name=exc_name;
609+
exc_symbol.name="java::"+id2string(exc_name);
610+
class_type.set(ID_name, exc_symbol.name);
611+
exc_symbol.type=class_type;
595612
exc_symbol.mode=ID_java;
596-
exc_symbol.type=typet(ID_pointer, empty_typet());
613+
exc_symbol.is_type=true;
597614
symbol_table.add(exc_symbol);
615+
// create the class identifier
616+
java_root_class(exc_symbol);
617+
618+
// create the exception object
619+
exc=object_factory(
620+
pointer_typet(exc_symbol.type),
621+
exc_name,
622+
init_code,
623+
false,
624+
symbol_table,
625+
max_array_length,
626+
original_loc);
598627
}
599628
else
600-
exc_symbol=symbol_table.lookup("ArrayIndexOutOfBoundsException");
629+
exc=symbol_table.lookup(exc_obj_name).symbol_expr();
601630

602-
const symbol_exprt &exc=exc_symbol.symbol_expr();
603631
side_effect_expr_throwt throw_expr;
604632
throw_expr.add_source_location()=original_loc;
605-
throw_expr.copy_to_operands(exc);
633+
throw_expr.move_to_operands(exc);
634+
635+
code_ifthenelset if_code;
636+
if_code.add_source_location()=original_loc;
637+
if_code.cond()=cond;
638+
if_code.then_case()=code_expressiont(throw_expr);
639+
640+
init_code.move_to_operands(if_code);
641+
642+
return init_code;
643+
}
644+
645+
/*******************************************************************\
646+
647+
Function: throw_array_access_exception
648+
649+
Inputs:
650+
651+
Outputs:
606652
653+
Purpose: Checks whether the array access array_struct[idx]
654+
is out-of-bounds, and throws ArrayIndexOutofBoundsException
655+
if necessary
656+
657+
\*******************************************************************/
658+
659+
codet java_bytecode_convert_methodt::throw_array_access_exception(
660+
const exprt &array_struct,
661+
const exprt &idx,
662+
const source_locationt &original_loc)
663+
{
607664
const constant_exprt &zero=from_integer(0, java_int_type());
608665
const binary_relation_exprt lt_zero(idx, ID_lt, zero);
609666
const member_exprt length_field(array_struct, "length", java_int_type());
610667
const binary_relation_exprt ge_length(idx, ID_ge, length_field);
611-
const and_exprt and_expr(lt_zero, ge_length);
668+
const or_exprt or_expr(lt_zero, ge_length);
612669

613-
code_ifthenelset if_code;
614-
if_code.add_source_location()=original_loc;
615-
if_code.cond()=and_expr;
616-
if_code.then_case()=code_expressiont(throw_expr);
617-
618-
return if_code;
670+
return throw_exception(
671+
or_expr,
672+
original_loc, "java.lang.ArrayIndexOutOfBoundsException");
619673
}
620674

621675
/*******************************************************************\
@@ -634,33 +688,12 @@ codet java_bytecode_convert_methodt::throw_array_length_exception(
634688
const exprt &length,
635689
const source_locationt &original_loc)
636690
{
637-
symbolt exc_symbol;
638-
if(!symbol_table.has_symbol("NegativeArraySizeException"))
639-
{
640-
exc_symbol.is_static_lifetime=true;
641-
exc_symbol.base_name="NegativeArraySizeException";
642-
exc_symbol.name="NegativeArraySizeException";
643-
exc_symbol.mode=ID_java;
644-
exc_symbol.type=typet(ID_pointer, empty_typet());
645-
symbol_table.add(exc_symbol);
646-
}
647-
else
648-
exc_symbol=symbol_table.lookup("NegativeArraySizeException");
649-
650-
const symbol_exprt &exc=exc_symbol.symbol_expr();
651-
side_effect_expr_throwt throw_expr;
652-
throw_expr.add_source_location()=original_loc;
653-
throw_expr.copy_to_operands(exc);
654-
655691
const constant_exprt &zero=from_integer(0, java_int_type());
656-
const binary_relation_exprt ge_zero(length, ID_ge, zero);
657-
658-
code_ifthenelset if_code;
659-
if_code.add_source_location()=original_loc;
660-
if_code.cond()=ge_zero;
661-
if_code.then_case()=code_expressiont(throw_expr);
692+
const binary_relation_exprt less_zero(length, ID_lt, zero);
662693

663-
return if_code;
694+
return throw_exception(
695+
less_zero,
696+
original_loc, "java.lang.NegativeArraySizeException");
664697
}
665698

666699
/*******************************************************************\
@@ -677,36 +710,22 @@ Function: throw_null_dereference_exception
677710
\*******************************************************************/
678711

679712
codet java_bytecode_convert_methodt::throw_null_dereference_exception(
680-
const exprt &expr,
713+
exprt &expr,
681714
const source_locationt &original_loc)
682715
{
683-
symbolt exc_symbol;
684-
if(!symbol_table.has_symbol("NullPointerException"))
685-
{
686-
exc_symbol.is_static_lifetime=true;
687-
exc_symbol.base_name="NullPointerException";
688-
exc_symbol.name="NullPointerException";
689-
exc_symbol.mode=ID_java;
690-
exc_symbol.type=typet(ID_pointer, empty_typet());
691-
symbol_table.add(exc_symbol);
692-
}
693-
else
694-
exc_symbol=symbol_table.lookup("NullPointerException");
716+
empty_typet voidt;
717+
pointer_typet voidptr(voidt);
695718

696-
const symbol_exprt &exc=exc_symbol.symbol_expr();
697-
side_effect_expr_throwt throw_expr;
698-
throw_expr.add_source_location()=original_loc;
699-
throw_expr.copy_to_operands(exc);
719+
if(expr.type()!=voidptr)
720+
expr.make_typecast(voidptr);
700721

701722
const equal_exprt equal_expr(
702723
expr,
703-
null_pointer_exprt(pointer_typet(empty_typet())));
704-
code_ifthenelset if_code;
705-
if_code.add_source_location()=original_loc;
706-
if_code.cond()=equal_expr;
707-
if_code.then_case()=code_expressiont(throw_expr);
724+
null_pointer_exprt(voidptr));
708725

709-
return if_code;
726+
return throw_exception(
727+
equal_expr,
728+
original_loc, "java.lang.NullPointerException");
710729
}
711730

712731
/*******************************************************************\
@@ -726,26 +745,6 @@ codet java_bytecode_convert_methodt::throw_class_cast_exception(
726745
const exprt &class2,
727746
const source_locationt &original_loc)
728747
{
729-
// TODO: use std::move
730-
symbolt exc_symbol;
731-
if(!symbol_table.has_symbol("ClassCastException"))
732-
{
733-
exc_symbol.is_static_lifetime=true;
734-
exc_symbol.base_name="ClassCastException";
735-
exc_symbol.name="ClassCastException";
736-
exc_symbol.mode=ID_java;
737-
exc_symbol.type=typet(ID_pointer, empty_typet());
738-
symbol_table.add(exc_symbol);
739-
}
740-
else
741-
exc_symbol=symbol_table.lookup("ClassCastException");
742-
743-
const symbol_exprt &exc=exc_symbol.symbol_expr();
744-
745-
side_effect_expr_throwt throw_expr;
746-
throw_expr.add_source_location()=original_loc;
747-
throw_expr.copy_to_operands(exc);
748-
749748
binary_predicate_exprt class_cast_check(
750749
class1, ID_java_instanceof, class2);
751750

@@ -757,14 +756,12 @@ codet java_bytecode_convert_methodt::throw_class_cast_exception(
757756
notequal_exprt op_not_null(null_check_op, null_pointer_exprt(voidptr));
758757

759758
// checkcast passes when the operand is null
760-
and_exprt and_expr(op_not_null, class_cast_check);
761-
762-
code_ifthenelset if_code;
763-
if_code.add_source_location()=original_loc;
764-
if_code.cond()=and_expr;
765-
if_code.then_case()=code_expressiont(throw_expr);
759+
and_exprt and_expr(op_not_null, not_exprt(class_cast_check));
766760

767-
return if_code;
761+
return throw_exception(
762+
and_expr,
763+
original_loc,
764+
"ClassCastException");
768765
}
769766

770767
/*******************************************************************\
@@ -1596,6 +1593,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
15961593
// on stack to given type fails.
15971594
// The stack isn't modified.
15981595
assert(op.size()==1 && results.size()==1);
1596+
15991597
if(throw_runtime_exceptions)
16001598
{
16011599
codet conditional_check=
@@ -1845,6 +1843,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
18451843
const dereference_exprt element(data_plus_offset, element_type);
18461844

18471845
c=code_blockt();
1846+
18481847
codet bounds_check=throw_runtime_exceptions?
18491848
throw_array_access_exception(deref, op[1], i_it->source_location):
18501849
get_array_bounds_check(deref, op[1], i_it->source_location);
@@ -2333,6 +2332,14 @@ codet java_bytecode_convert_methodt::convert_instructions(
23332332
else if(statement=="getfield")
23342333
{
23352334
assert(op.size()==1 && results.size()==1);
2335+
if(throw_runtime_exceptions)
2336+
{
2337+
codet null_dereference_check=
2338+
throw_null_dereference_exception(
2339+
op[0],
2340+
i_it->source_location);
2341+
c=null_dereference_check;
2342+
}
23362343
results[0]=java_bytecode_promotion(to_member(op[0], arg0));
23372344
}
23382345
else if(statement=="getstatic")
@@ -2360,6 +2367,14 @@ codet java_bytecode_convert_methodt::convert_instructions(
23602367
else if(statement=="putfield")
23612368
{
23622369
assert(op.size()==2 && results.size()==0);
2370+
if(throw_runtime_exceptions)
2371+
{
2372+
codet null_dereference_check=
2373+
throw_null_dereference_exception(
2374+
op[0],
2375+
i_it->source_location);
2376+
c=null_dereference_check;
2377+
}
23632378
c=code_assignt(to_member(op[0], arg0), op[1]);
23642379
}
23652380
else if(statement=="putstatic")

0 commit comments

Comments
 (0)