rspec/rules/S3518/python/rule.adoc

114 lines
2.6 KiB
Plaintext

If the denominator to a division or modulo operation is zero, a
`ZeroDivisionError` is raised.
include::../introduction.adoc[]
== Why is this an issue?
A division (`/`) or modulo operation (`%`) by zero indicates a bug or logical
error.
This is because in Python, a division or modulo operation where the denominator
is zero always results in a `ZeroDivisionError` being raised.
include::../impact.adoc[]
== How to fix it
The goal is to ensure that a zero value never reaches the denominator.
=== Code examples
==== Noncompliant code example
[source,python,diff-id=1,diff-type=noncompliant]
----
def foo():
z = 0
if (unknown()):
# ...
z = 4
else:
# ...
# (z is not reassigned to a non-zero value here)
z = 1 / z
----
==== Compliant solution
[source,python,diff-id=1,diff-type=compliant]
----
def foo():
z = 0
if (unknown()):
# ...
z = 4
else:
# ...
z = 1
z = 1 / z
----
==== Noncompliant code example
[source,python,diff-id=2,diff-type=noncompliant]
----
def report_average():
sum = compute_sum()
denominator = population()
print(sum / denominator) # Noncompliant: divisor can be 0
def population():
size = read_size()
return size if size is not None else 0
----
==== Compliant solution
[source,python,diff-id=2,diff-type=compliant]
----
def report_average():
sum = compute_sum()
denominator = population()
if denominator == 0:
print("We have no data.")
else:
print(sum / denominator)
def population():
size = read_size()
return size if size is not None else 0
----
=== How does this work?
One approach is to inspect every possible execution path that affects the
denominator and adjust them such that none of them lead to a zero value.
The first example illustrates this by ensuring that for all the paths that can
define the variable ++z++, none assign it zero.
Thus, we are sure that the issue is fixed.
In other cases it might be necessary and safer to check and explicitly handle
the case of a zero denominator.
For instance, in the second example, an error message is displayed to the user
if the denominator is zero.
//=== Pitfalls
//=== Going the extra mile
== Resources
=== Documentation
* https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations[Binary arithmetic operations]
* https://docs.python.org/3/library/exceptions.html#ZeroDivisionError[ZeroDivisionError]
=== Articles & blog posts
* https://cwe.mitre.org/data/definitions/369[MITRE, CWE-369] - Divide by zero
//=== Articles & blog posts
//=== Conference presentations
//=== Standards