Skip to content

Commit fe46bed

Browse files
authored
Merge pull request #1200 from smowton/feature/throw-arithmetic-exception
Throw on divide-by-zero
2 parents ce7c498 + fb89e5a commit fe46bed

20 files changed

+160
-0
lines changed
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class ArithmeticExceptionTest {
2+
public static void main(String args[]) {
3+
try {
4+
int i=0;
5+
int j=10/i;
6+
}
7+
catch(ArithmeticException exc) {
8+
assert false;
9+
}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArithmeticExceptionTest.class
3+
--java-throw-runtime-exceptions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^.*assertion at file ArithmeticExceptionTest.java line 8 function.*: FAILURE$
7+
^VERIFICATION FAILED
8+
--
9+
^warning: ignoring
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public class ArithmeticExceptionTest {
2+
public static void main(String args[]) {
3+
try {
4+
long denom=0;
5+
long num=10;
6+
long j=num/denom;
7+
}
8+
catch(ArithmeticException exc) {
9+
assert false;
10+
}
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArithmeticExceptionTest.class
3+
--java-throw-runtime-exceptions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^.*assertion at file ArithmeticExceptionTest.java line 9 function.*: FAILURE$
7+
^VERIFICATION FAILED
8+
--
9+
^warning: ignoring
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class ArithmeticExceptionTest {
2+
public static void main(String args[]) {
3+
try {
4+
int i=0;
5+
int j=10%i;
6+
}
7+
catch(ArithmeticException exc) {
8+
assert false;
9+
}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArithmeticExceptionTest.class
3+
--java-throw-runtime-exceptions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^.*assertion at file ArithmeticExceptionTest.java line 8 function.*: FAILURE$
7+
^VERIFICATION FAILED
8+
--
9+
^warning: ignoring
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public class ArithmeticExceptionTest {
2+
public static void main(String args[]) {
3+
try {
4+
long denom=0;
5+
long num=10;
6+
long result=num%denom;
7+
}
8+
catch(ArithmeticException exc) {
9+
assert false;
10+
}
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArithmeticExceptionTest.class
3+
--java-throw-runtime-exceptions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^.*assertion at file ArithmeticExceptionTest.java line 9 function.*: FAILURE$
7+
^VERIFICATION FAILED
8+
--
9+
^warning: ignoring
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class ArithmeticExceptionTest {
2+
public static void main(String args[]) {
3+
try {
4+
double i=0;
5+
double j=10/i;
6+
}
7+
catch(ArithmeticException exc) {
8+
assert false;
9+
}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
ArithmeticExceptionTest.class
3+
--java-throw-runtime-exceptions
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL
7+
--
8+
^warning: ignoring
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
public class ArithmeticExceptionTest {
2+
public static void main(int denom) {
3+
try {
4+
int j=10/denom;
5+
}
6+
catch(ArithmeticException exc) {
7+
assert false;
8+
}
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArithmeticExceptionTest.class
3+
--java-throw-runtime-exceptions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^.*assertion at file ArithmeticExceptionTest.java line 7 function.*: FAILURE$
7+
^VERIFICATION FAILED
8+
--
9+
^warning: ignoring

src/java_bytecode/java_bytecode_convert_method.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,10 @@ codet java_bytecode_convert_methodt::convert_instructions(
10521052
i_it->statement=="checkcast" ||
10531053
i_it->statement=="newarray" ||
10541054
i_it->statement=="anewarray" ||
1055+
i_it->statement=="idiv" ||
1056+
i_it->statement=="ldiv" ||
1057+
i_it->statement=="irem" ||
1058+
i_it->statement=="lrem" ||
10551059
i_it->statement==patternt("?astore") ||
10561060
i_it->statement==patternt("?aload") ||
10571061
i_it->statement=="invokestatic" ||

src/java_bytecode/java_bytecode_instrument.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class java_bytecode_instrumentt:public messaget
5757
const exprt &idx,
5858
const source_locationt &original_loc);
5959

60+
codet check_arithmetic_exception(
61+
const exprt &denominator,
62+
const source_locationt &original_loc);
63+
6064
codet check_null_dereference(
6165
const exprt &expr,
6266
const source_locationt &original_loc,
@@ -132,6 +136,30 @@ codet java_bytecode_instrumentt::throw_exception(
132136
return if_code;
133137
}
134138

139+
140+
/// Checks whether there is a division by zero
141+
/// and throws ArithmeticException if necessary.
142+
/// Exceptions are thrown when the `throw_runtime_exceptions`
143+
/// flag is set.
144+
/// \return Based on the value of the flag `throw_runtime_exceptions`,
145+
/// it returns code that either throws an ArithmeticException
146+
/// or is a skip
147+
codet java_bytecode_instrumentt::check_arithmetic_exception(
148+
const exprt &denominator,
149+
const source_locationt &original_loc)
150+
{
151+
const constant_exprt &zero=from_integer(0, denominator.type());
152+
const binary_relation_exprt equal_zero(denominator, ID_equal, zero);
153+
154+
if(throw_runtime_exceptions)
155+
return throw_exception(
156+
equal_zero,
157+
original_loc,
158+
"java.lang.ArithmeticException");
159+
160+
return code_skipt();
161+
}
162+
135163
/// Checks whether the array access array_struct[idx] is out-of-bounds,
136164
/// and throws ArrayIndexOutofBoundsException/generates an assertion
137165
/// if necessary; Exceptions are thrown when the `throw_runtime_exceptions`
@@ -463,6 +491,14 @@ codet java_bytecode_instrumentt::instrument_expr(
463491
expr.op0(),
464492
expr.source_location());
465493
}
494+
else if((expr.id()==ID_div || expr.id()==ID_mod) &&
495+
expr.type().id()==ID_signedbv)
496+
{
497+
// check division by zero (for integer types only)
498+
return check_arithmetic_exception(
499+
expr.op1(),
500+
expr.source_location());
501+
}
466502
else if(expr.id()==ID_member &&
467503
expr.get_bool(ID_java_member_access))
468504
{

0 commit comments

Comments
 (0)