Skip to content

[Guideline] Add do not divide by 0 #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions src/coding-guidelines/expressions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,75 @@ Expressions
fn with_base(_: &Base) { ... }


.. guideline:: Do not divide by 0
:id: gui_kMbiWbn8Z6g5
:category: required
:status: draft
:release: latest
:fls: fls_Q9dhNiICGIfr
:decidability: undecidable
:scope: system
:tags: numerics, defect

This guideline applies when unsigned integer or two’s complement division is performed during the
evaluation of an `ArithmeticExpression
<https://rust-lang.github.io/fls/expressions.html#arithmetic-expressions>`_.

This includes the evaluation of a `RemainderExpression
<https://rust-lang.github.io/fls/expressions.html#syntax_remainderexpression>`_, which uses unsigned integer or two's
complement division.

This rule does not apply to evaluation of a :std:`core::ops::Div` trait on types other than `integer
types <https://rust-lang.github.io/fls/types-and-traits.html#integer-types>`_.

.. rationale::
:id: rat_h84NjY2tLSBW
:status: draft

Integer division by zero results in a panic, which is an abnormal program state and may terminate the
process. The use of :std:`std::num::NonZero` as the divisor is a recommended way to avoid the
undecidability of this guideline.

.. non_compliant_example::
:id: non_compl_ex_LLs3vY8aGz0F
:status: draft

When the division is performed, the right operand is evaluated to zero and the program panics.

.. code-block:: rust

let x = 0;
let y = 5 / x; // This line will panic.

.. compliant_example::
:id: compl_ex_Ri9pP5Ch3kbb
:status: draft

There is no compliant way to perform integer division by zero. A checked division will prevent any
division by zero from happening. The programmer can then handle the returned :std:`std::option::Option`.

The check for zero can also be performed manually. However, as the complexity of the control
flow leading to the invariant increases, it becomes increasingly harder to reason about it. For both programmers and static analysis tools.

.. code-block:: rust

// Example 1: using the checked division API
let result = match 5u8.checked_div(0) {
None => 0
Some(r) => r
};

// Example 2: performing zero-checks by hand
let x = 0;
let y = if x != 0 {
5 / x
} else {
0
};




.. guideline:: The 'as' operator should not be used with numeric operands
:id: gui_ADHABsmK9FXz
:category: advisory
Expand Down