2023-05-19 17:19:56 +02:00
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
If the denominator to a division or modulo operation is zero, a
|
|
|
|
`ZeroDivisionError` is raised.
|
|
|
|
|
|
|
|
include::../introduction.adoc[]
|
2023-05-19 17:19:56 +02:00
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
== Why is this an issue?
|
2023-05-19 17:19:56 +02:00
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
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.
|
2023-05-19 17:19:56 +02:00
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
include::../impact.adoc[]
|
2023-05-19 17:19:56 +02:00
|
|
|
|
|
|
|
== How to fix it
|
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
The goal is to ensure that a zero value never reaches the denominator.
|
2023-05-19 17:19:56 +02:00
|
|
|
|
|
|
|
=== Code examples
|
|
|
|
|
|
|
|
==== Noncompliant code example
|
|
|
|
|
2023-05-25 14:18:12 +02:00
|
|
|
[source,python,diff-id=1,diff-type=noncompliant]
|
2023-05-19 17:19:56 +02:00
|
|
|
----
|
2023-09-28 11:35:02 +02:00
|
|
|
def foo():
|
2023-05-19 17:19:56 +02:00
|
|
|
z = 0
|
|
|
|
if (unknown()):
|
|
|
|
z = 4
|
2023-12-11 16:04:59 +01:00
|
|
|
...
|
2023-05-19 17:19:56 +02:00
|
|
|
else:
|
2023-09-28 11:35:02 +02:00
|
|
|
# (z is not reassigned to a non-zero value here)
|
2023-12-11 16:04:59 +01:00
|
|
|
...
|
|
|
|
z = 1 / z # Noncompliant: divisor can be 0
|
2023-05-19 17:19:56 +02:00
|
|
|
----
|
|
|
|
|
|
|
|
==== Compliant solution
|
|
|
|
|
2023-05-25 14:18:12 +02:00
|
|
|
[source,python,diff-id=1,diff-type=compliant]
|
2023-05-19 17:19:56 +02:00
|
|
|
----
|
2023-09-28 11:35:02 +02:00
|
|
|
def foo():
|
2023-05-19 17:19:56 +02:00
|
|
|
z = 0
|
|
|
|
if (unknown()):
|
|
|
|
z = 4
|
2023-12-11 16:04:59 +01:00
|
|
|
...
|
2023-05-19 17:19:56 +02:00
|
|
|
else:
|
|
|
|
z = 1
|
2023-12-11 16:04:59 +01:00
|
|
|
...
|
2023-05-19 17:19:56 +02:00
|
|
|
z = 1 / z
|
|
|
|
----
|
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
==== 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
|
|
|
|
----
|
|
|
|
|
2023-05-19 17:19:56 +02:00
|
|
|
=== How does this work?
|
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
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.
|
2023-05-19 17:19:56 +02:00
|
|
|
|
|
|
|
//=== Pitfalls
|
|
|
|
|
|
|
|
//=== Going the extra mile
|
|
|
|
|
2023-09-28 11:35:02 +02:00
|
|
|
== 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
|
|
|
|
|
2024-01-15 17:15:56 +01:00
|
|
|
* CWE - https://cwe.mitre.org/data/definitions/369[CWE-369 - Divide by zero]
|
2023-05-19 17:19:56 +02:00
|
|
|
|
|
|
|
//=== Articles & blog posts
|
|
|
|
//=== Conference presentations
|
|
|
|
//=== Standards
|