Checked arithmetic

In PolicyCenter version 8.0 and earlier versions, 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 occurred, it was difficult to protect against overflow errors, which could cause unexpected behavior or security issues.

In version 9.0, 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.

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.

There are special cases in which 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 new 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 Java system property checkedArithmetic to true:

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.