Checked arithmetic for add, subtract, and multiply

By default, numeric values could exceed their defined bounds in arithmetic operations. For example, if you multiplied the maximum integer value by 2, the result by definition exceeds the range of integer values. Not only is the result value incorrect, the result could be positive when you expect it to be negative, or negative when you expect it to be positive. Because no Gosu exceptions occur, writing code to protect against overflow errors, which could cause unexpected behavior or security issues, is difficult.

Gosu includes an optional feature called checked arithmetic. If checked arithmetic is enabled, Gosu behavior for the standard arithmetic operators changes for addition, subtraction, and multiplication. In nearly all cases, the result is the same and the behavior is the same. In the rare case that arithmetic overflow occurs, Gosu throws the exception ArithmeticException.

To enable checked arithmetic, set Java system property checkedArithmetic to true when launching Studio and when launching the application server.

Gosu checked arithmetic includes protection only for the operators +, -, and *. There is no protection for division, which only affects the expression Integer.MIN_VALUE / -1.

In some cases, arithmetic overflow behaviors are desirable for operators +, -, and *. For example, some common hash algorithms rely on arithmetic overflow. To handle typical use cases in overridden hashCode methods, Gosu always compiles hashCode methods with checked arithmetic disabled.

For other cases in which arithmetic overflow behaviors are desirable, you can use three Gosu operators that ensure unchecked arithmetic independent of the Java system property checkedArithmetic. The new operators are the standard arithmetic operators prefaced with an exclamation point character: !+, !-, and !*.

For example, with checked arithmetic enabled:

var four = new Integer(4)
var y = Integer.MAX_VALUE * 2 + four // This line throws ArithmeticException

In contrast, the following example uses the unchecked arithmetic operator !*, which is only for special circumstances in which overflow is desirable:

var four = new Integer(4)
var x = Integer.MAX_VALUE !* 2 + four // This line does not throw ArithmeticException
print(x) // Print "2"

Because the arithmetic in the second example is unchecked, the result that prints 2 successfully is possibly unexpected and invalid.

See also