Skip to content

Commit 73f621f

Browse files
authored
Clarify arithmetic overflow handling and examples
Clarified behavior of arithmetic overflow in debug and release modes. Updated examples to emphasize the use of explicit wrapping and saturation semantics.
1 parent 3083d2e commit 73f621f

1 file changed

Lines changed: 18 additions & 11 deletions

File tree

src/coding-guidelines/expressions.rst

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ Expressions
1818
:tags: security, performance, numerics
1919

2020
Eliminate `arithmetic overflow <https://rust-lang.github.io/fls/expressions.html#arithmetic-overflow>`_ of both signed and unsigned integer types.
21-
Arithmetic overflow will panic in debug mode, but wraparound in release mode.
2221
Any wraparound behavior must be explicitly specified to ensure the same behavior in both debug and release modes.
2322

2423
This rule applies to the following primitive types:
@@ -41,7 +40,9 @@ Expressions
4140
:status: draft
4241

4342
Eliminate arithmetic overflow to avoid runtime panics and unexpected wraparound behavior.
44-
Use explicit wrapping or saturation semantics in cases where these behaviors are intentional.
43+
Arithmetic overflow will panic in debug mode, but wraparound in release mode, resulting in inconsistent behavior.
44+
Use explicit `wrapping <https://doc.rust-lang.org/std/num/struct.Wrapping.html>`_ or
45+
`saturating <https://doc.rust-lang.org/std/num/struct.Saturating.html>`_ semantics where these behaviors are intentional.
4546
Range checking can be used to eliminate the possibility of arithmetic overflow.
4647

4748
.. non_compliant_example::
@@ -61,20 +62,26 @@ Expressions
6162
:id: compl_ex_BgUHiRB4kc4b_1
6263
:status: draft
6364

64-
This compliant solution ensures that the addition operation cannot result
65-
in arithmetic overflow, based on the maximum range of a signed 32-bit integer.
66-
A more restrictive range may also be used.
65+
This compliant solution ensures that the addition operation cannot result in arithmetic overflow,
66+
based on the maximum range of a signed 32-bit integer.
67+
Functions such as
68+
`overflowing_add <https://doc.rust-lang.org/stable/core/primitive.u32.html#method.overflowing_add>`_,
69+
`overflowing_sub <https://doc.rust-lang.org/stable/core/primitive.u32.html#method.overflowing_sub>`_, and
70+
`overflowing_mul <https://doc.rust-lang.org/stable/core/primitive.u32.html#method.overflowing_mul>`_
71+
can also be used to detect overflow.
72+
Code that invoked these functions would typically further restrict the range of possible values,
73+
based on the anticipated range of the inputs.
6774

6875
.. code-block:: rust
6976
7077
enum ArithmeticError {
7178
Overflow,
72-
DivisionByZero,
79+
DivisionByZero,
7380
}
7481
7582
use std::i32::{MAX as INT_MAX, MIN as INT_MIN};
7683
77-
fn add(si_a: i32, si_b: i32) -> Result<i32, ArithmeticError> {
84+
fn add(si_a: i32, si_b: i32) -> Result<i32, ArithmeticError> {
7885
if (si_b > 0 && si_a > INT_MAX - si_b)
7986
|| (si_b < 0 && si_a < INT_MIN - si_b)
8087
{
@@ -88,13 +95,13 @@ Expressions
8895
if (si_b < 0 && si_a > INT_MAX + si_b)
8996
|| (si_b > 0 && si_a < INT_MIN + si_b)
9097
{
91-
Err(ArithmeticError::Overflow)
98+
Err(ArithmeticError::Overflow)
9299
} else {
93-
Ok(si_a - si_b)
100+
Ok(si_a - si_b)
94101
}
95102
}
96103
97-
fn mul(si_a: i32, si_b: i32) -> Result<i32, ArithmeticError> {
104+
fn mul(si_a: i32, si_b: i32) -> Result<i32, ArithmeticError> {
98105
if si_a == 0 || si_b == 0 {
99106
return Ok(0);
100107
}
@@ -180,7 +187,7 @@ Expressions
180187
fn main() {
181188
let si_a = Wrapping(i32::MAX);
182189
let si_b = Wrapping(i32::MAX);
183-
println!("Adding {} by {} has a sum of {}", si_a, si_b, add(si_a, si_b))
190+
println!("{} + {} = {}", si_a, si_b, add(si_a, si_b))
184191
}
185192
186193
.. compliant_example::

0 commit comments

Comments
 (0)