Skip to content

Commit d695610

Browse files
vapdrsPLeVasseurAlexCelestefelix91gr
authored
[Guideline] Add do not divide by 0 (#132)
* [Guideline] Add do not divide by 0 * Remove example code from compliant example As stated there is no compliant way to do this, so no example should be present. * Add compliant example with a suggestion While the guideline does not strictly apply to this example, it is a good suggestion for what to do instead. * Lowercasing of guideline metadata Co-authored-by: Pete LeVasseur <[email protected]> * Add Rust std link transformation Co-authored-by: Pete LeVasseur <[email protected]> * Clarify scope of expressions this applies to * Remove "Note" phrase It is not recommended for normative language Co-authored-by: Alex Eris Celeste née Gilding <[email protected]> * Add missing phrase to NonZero recommendation Also moved to the Rationale. * Example compliant example with a match expression * Downgrade guideline to Required Mandatory is a bit strong for panics as determined in today's meeting. * Add compliant manual check example * Add defect tag * Formatting and prose improvements Co-authored-by: Félix Fischer <[email protected]> * Adding more explanation to the examples Co-authored-by: Félix Fischer <[email protected]> --------- Co-authored-by: Pete LeVasseur <[email protected]> Co-authored-by: Alex Eris Celeste née Gilding <[email protected]> Co-authored-by: Alex Eris Celeste née Gilding <[email protected]> Co-authored-by: Félix Fischer <[email protected]>
1 parent 6412306 commit d695610

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/coding-guidelines/expressions.rst

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,75 @@ Expressions
8383
fn with_base(_: &Base) { ... }
8484
8585
86+
.. guideline:: Do not divide by 0
87+
:id: gui_kMbiWbn8Z6g5
88+
:category: required
89+
:status: draft
90+
:release: latest
91+
:fls: fls_Q9dhNiICGIfr
92+
:decidability: undecidable
93+
:scope: system
94+
:tags: numerics, defect
95+
96+
This guideline applies when unsigned integer or two’s complement division is performed during the
97+
evaluation of an `ArithmeticExpression
98+
<https://rust-lang.github.io/fls/expressions.html#arithmetic-expressions>`_.
99+
100+
This includes the evaluation of a `RemainderExpression
101+
<https://rust-lang.github.io/fls/expressions.html#syntax_remainderexpression>`_, which uses unsigned integer or two's
102+
complement division.
103+
104+
This rule does not apply to evaluation of a :std:`core::ops::Div` trait on types other than `integer
105+
types <https://rust-lang.github.io/fls/types-and-traits.html#integer-types>`_.
106+
107+
.. rationale::
108+
:id: rat_h84NjY2tLSBW
109+
:status: draft
110+
111+
Integer division by zero results in a panic, which is an abnormal program state and may terminate the
112+
process. The use of :std:`std::num::NonZero` as the divisor is a recommended way to avoid the
113+
undecidability of this guideline.
114+
115+
.. non_compliant_example::
116+
:id: non_compl_ex_LLs3vY8aGz0F
117+
:status: draft
118+
119+
When the division is performed, the right operand is evaluated to zero and the program panics.
120+
121+
.. code-block:: rust
122+
123+
let x = 0;
124+
let y = 5 / x; // This line will panic.
125+
126+
.. compliant_example::
127+
:id: compl_ex_Ri9pP5Ch3kbb
128+
:status: draft
129+
130+
There is no compliant way to perform integer division by zero. A checked division will prevent any
131+
division by zero from happening. The programmer can then handle the returned :std:`std::option::Option`.
132+
133+
The check for zero can also be performed manually. However, as the complexity of the control
134+
flow leading to the invariant increases, it becomes increasingly harder to reason about it. For both programmers and static analysis tools.
135+
136+
.. code-block:: rust
137+
138+
// Example 1: using the checked division API
139+
let result = match 5u8.checked_div(0) {
140+
None => 0
141+
Some(r) => r
142+
};
143+
144+
// Example 2: performing zero-checks by hand
145+
let x = 0;
146+
let y = if x != 0 {
147+
5 / x
148+
} else {
149+
0
150+
};
151+
152+
153+
154+
86155
.. guideline:: The 'as' operator should not be used with numeric operands
87156
:id: gui_ADHABsmK9FXz
88157
:category: advisory

0 commit comments

Comments
 (0)