From 9b3b79f51cd87090fc7a24ed7fe857ba2b920d01 Mon Sep 17 00:00:00 2001 From: Anton Haubner Date: Thu, 28 Sep 2023 11:35:02 +0200 Subject: [PATCH] Modify rule S3518: More LaYC Content for Python and Java (#3167) --- rules/S3518/impact.adoc | 6 ++ rules/S3518/introduction.adoc | 4 ++ rules/S3518/java/rule.adoc | 71 ++++++++++++++++++--- rules/S3518/python/rule.adoc | 76 +++++++++++++++++++---- rules/S6466/impact.adoc | 5 +- shared_content/layc/exception-impact.adoc | 4 ++ 6 files changed, 143 insertions(+), 23 deletions(-) create mode 100644 rules/S3518/impact.adoc create mode 100644 rules/S3518/introduction.adoc create mode 100644 shared_content/layc/exception-impact.adoc diff --git a/rules/S3518/impact.adoc b/rules/S3518/impact.adoc new file mode 100644 index 00000000000..0718edbb0e9 --- /dev/null +++ b/rules/S3518/impact.adoc @@ -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. diff --git a/rules/S3518/introduction.adoc b/rules/S3518/introduction.adoc new file mode 100644 index 00000000000..9147a1fea5a --- /dev/null +++ b/rules/S3518/introduction.adoc @@ -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. diff --git a/rules/S3518/java/rule.adoc b/rules/S3518/java/rule.adoc index 210cb181a02..c21f7998d72 100644 --- a/rules/S3518/java/rule.adoc +++ b/rules/S3518/java/rule.adoc @@ -1,22 +1,74 @@ -== 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. +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. + +include::../impact.adoc[] + +=== Noncompliant code example + +[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 +} +---- + +=== 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[] @@ -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[] diff --git a/rules/S3518/python/rule.adoc b/rules/S3518/python/rule.adoc index b558a3795a4..b352ed41e49 100644 --- a/rules/S3518/python/rule.adoc +++ b/rules/S3518/python/rule.adoc @@ -1,16 +1,21 @@ -If the denominator to a division or modulo operation is zero it would result in a fatal error. -== Why is this an issue? +If the denominator to a division or modulo operation is zero, a +`ZeroDivisionError` is raised. + +include::../introduction.adoc[] -This is an issue because dividing by zero is a forbidden operation which leads to a fatal error. +== Why is this an issue? -=== What is the potential impact? +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. -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 diff --git a/rules/S6466/impact.adoc b/rules/S6466/impact.adoc index ab7f007ac0b..49eab79ba5e 100644 --- a/rules/S6466/impact.adoc +++ b/rules/S6466/impact.adoc @@ -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. diff --git a/shared_content/layc/exception-impact.adoc b/shared_content/layc/exception-impact.adoc new file mode 100644 index 00000000000..c9b861601e0 --- /dev/null +++ b/shared_content/layc/exception-impact.adoc @@ -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.