Skip to content

Commit

Permalink
Modify rule S3518: More LaYC Content for Python and Java
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-haubner-sonarsource committed Sep 27, 2023
1 parent f0dc2a2 commit 33ea075
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 22 deletions.
6 changes: 6 additions & 0 deletions rules/S3518/impact.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
=== What is the potential impact?

include::../../shared_content/layc/exception-impact.adoc[]

If the computation of the denominator is tied to user input data, this issue can
potentially even be exploited by attackers to disrupt your application.
4 changes: 4 additions & 0 deletions rules/S3518/introduction.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This error will crash your program in most cases.
To fix it, you need to ensure that the denominator value in all division
operations is always non-zero, or check the value against zero before performing
the division.
71 changes: 63 additions & 8 deletions rules/S3518/java/rule.adoc
Original file line number Diff line number Diff line change
@@ -1,29 +1,84 @@
== Why is this an issue?

If the denominator to a division or modulo operation is zero it would result in a fatal error.
If the denominator to an integer division or remainder operation is zero, a
`ArithmeticException` is thrown.

include::../introduction.adoc[]

When working with ``++double++`` or ``++float++``, no fatal error will be raised, but it will lead to unusual result and should be avoided anyway.
== Why is this an issue?

A division (`/`) or remainder operation (`%`) by zero indicates a bug or logical
error.

In Java, a division or remainder operation where the denominator is zero and not
a floating point value always results in an `ArithmeticException` being thrown.

When working with ``++double++`` or ``++float++`` values, no exception will be
thrown, but the operation will result in special floating point values
representing either positive infinity, negative infinity, or `NaN`.
Unless these special values are explicitly handled by a program, zero
denominators should be avoided in floating point operations, too.
Otherwise, the application might produce unexpected results.

include::../impact.adoc[]

=== Noncompliant code example

[source,java,diff-id=1,diff-type=compliant]
----
void test_divide() {
int z = 0;
if (unknown()) {
// ..
z = 3;
} else {
// ..
}
z = 1 / z; // Noncompliant, possible division by zero
}
----

=== Compliant solution

[source,java,diff-id=1,diff-type=compliant]
----
void test_divide() {
int z = 0;
if (unknown()) {
// ..
z = 3;
} else {
// ..
z = 1;
}
z = 1 / z;
}
----

This rule supports primitive ``++int++``, ``++long++``, ``++double++``, ``++float++`` as well as ``++BigDecimal++`` and ``++BigInteger++``.
== Resources

include::../noncompliant.adoc[]
=== Documentation

include::../compliant.adoc[]
* https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/ArithmeticException.html[ArithmeticException]

== Resources
=== Articles & blog posts

* https://cwe.mitre.org/data/definitions/369[MITRE, CWE-369] - Divide by zero
* https://wiki.sei.cmu.edu/confluence/x/CTZGBQ[CERT, NUM02-J.] - Ensure that division and remainder operations do not result in divide-by-zero errors
* https://wiki.sei.cmu.edu/confluence/x/ftYxBQ[CERT, INT33-C.] - Ensure that division and remainder operations do not result in divide-by-zero errors

=== Standards

* https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.17.2[The Division Operator in the JLS]
* https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.17.3[The Remainder Operator in the JLS]

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

This rule supports primitive ``++int++``, ``++long++``, ``++double++``, and
``++float++`` values, as well as ``++BigDecimal++`` and ``++BigInteger++``.

include::../message.adoc[]

include::../highlighting.adoc[]
Expand Down
75 changes: 65 additions & 10 deletions rules/S3518/python/rule.adoc
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
If the denominator to a division or modulo operation is zero it would result in a fatal error.

If the denominator to a division or modulo operation is zero, a
`ZeroDivisionError` is raised.

include::../introduction.adoc[]

== Why is this an issue?

This is an issue because dividing by zero is a forbidden operation which leads to a fatal error.
A division (`/`) or modulo operation (`%`) by zero indicates a bug or logical
error.

=== What is the potential impact?
In Python, a division or modulo operation where the denominator is zero always
results in a `ZeroDivisionError` being raised.

This issue can lead your program to an unexpected halt with all the inconveniences it entails.
include::../impact.adoc[]

== How to fix it

Make sure that zero never reaches the denominator.
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 non_compliant():
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 compliant():
def foo():
z = 0
if (unknown()):
# ...
Expand All @@ -43,17 +50,65 @@ def compliant():
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?

By ensuring that for all the paths that can define the variable ++z++, when none assigns it zero, we are sure that the issue is fixed.
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

//== Resources
//=== Documentation
//=== Articles & blog posts
//=== Conference presentations
//=== Standards
5 changes: 1 addition & 4 deletions rules/S6466/impact.adoc
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
=== What is the potential impact?

Issues of this type interrupt the normal execution of a program, causing it to
crash or putting it into an inconsistent state.
Therefore, this issue might impact the availability and reliability of your
application, or even result in data loss.
include::../../shared_content/layc/exception-impact.adoc[]

If the computation of an index value is tied to user input data, this issue can
potentially even be exploited by attackers to disrupt your application.
4 changes: 4 additions & 0 deletions shared_content/layc/exception-impact.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Issues of this type interrupt the normal execution of a program, causing it to
crash or putting it into an inconsistent state.
Therefore, this issue might impact the availability and reliability of your
application, or even result in data loss.

0 comments on commit 33ea075

Please sign in to comment.