Modify rule S3518: More LaYC Content for Python and Java (#3167)
This commit is contained in:
parent
b965af0518
commit
9b3b79f51c
6
rules/S3518/impact.adoc
Normal file
6
rules/S3518/impact.adoc
Normal file
@ -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
rules/S3518/introduction.adoc
Normal file
4
rules/S3518/introduction.adoc
Normal file
@ -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.
|
@ -1,22 +1,74 @@
|
||||
|
||||
If the denominator to an integer division or remainder operation is zero, a
|
||||
`ArithmeticException` is thrown.
|
||||
|
||||
include::../introduction.adoc[]
|
||||
|
||||
== Why is this an issue?
|
||||
|
||||
If the denominator to a division or modulo operation is zero it would result in a fatal error.
|
||||
A division (`/`) or remainder operation (`%`) by zero indicates a bug or logical
|
||||
error.
|
||||
This is because 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.
|
||||
|
||||
When working with ``++double++`` or ``++float++``, no fatal error will be raised, but it will lead to unusual result and should be avoided anyway.
|
||||
include::../impact.adoc[]
|
||||
|
||||
=== Noncompliant code example
|
||||
|
||||
This rule supports primitive ``++int++``, ``++long++``, ``++double++``, ``++float++`` as well as ``++BigDecimal++`` and ``++BigInteger++``.
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
void test_divide() {
|
||||
int z = 0;
|
||||
if (unknown()) {
|
||||
// ..
|
||||
z = 3;
|
||||
} else {
|
||||
// ..
|
||||
}
|
||||
z = 1 / z; // Noncompliant, possible division by zero
|
||||
}
|
||||
----
|
||||
|
||||
include::../noncompliant.adoc[]
|
||||
=== Compliant solution
|
||||
|
||||
include::../compliant.adoc[]
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
void test_divide() {
|
||||
int z = 0;
|
||||
if (unknown()) {
|
||||
// ..
|
||||
z = 3;
|
||||
} else {
|
||||
// ..
|
||||
z = 1;
|
||||
}
|
||||
z = 1 / z;
|
||||
}
|
||||
----
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/ArithmeticException.html[ArithmeticException]
|
||||
|
||||
=== 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[]
|
||||
|
||||
@ -24,6 +76,9 @@ 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[]
|
||||
|
@ -1,16 +1,21 @@
|
||||
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.
|
||||
This is because in Python, a division or modulo operation where the denominator
|
||||
is zero always results in a `ZeroDivisionError` being raised.
|
||||
|
||||
=== What is the potential impact?
|
||||
|
||||
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
|
||||
|
||||
@ -18,13 +23,14 @@ Make sure that zero never reaches the denominator.
|
||||
|
||||
[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
|
||||
----
|
||||
|
||||
@ -32,7 +38,7 @@ def non_compliant():
|
||||
|
||||
[source,python,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
def compliant():
|
||||
def foo():
|
||||
z = 0
|
||||
if (unknown()):
|
||||
# ...
|
||||
@ -43,17 +49,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
|
||||
|
@ -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
shared_content/layc/exception-impact.adoc
Normal file
4
shared_content/layc/exception-impact.adoc
Normal file
@ -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.
|
Loading…
x
Reference in New Issue
Block a user