Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-681/01/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# CWE-681: Avoid an uncontrolled loss of precision when passing floating-point literals to a Decimal constructor

When working with decimal numbers in Python, using floating-point literals as input to the `Decimal` constructor can lead to unintended imprecision due to the limitations of `IEEE 754` [Wikipedia 2025](https://en.wikipedia.org/wiki/IEEE_754) floating-point representation; therefore, to ensure accurate decimal representation, it is advisable to avoid using floating-point literals.

## Noncompliant Code Example

In the `noncompliant01.py` code example, a floating-point value is given to the Decimal constructor. The decimal `0.45` cannot be exactly represented by a floating-point literal, and hence the output of the decimal is imprecise. This is because `0.45` as a floating-point representation deals with the number in binary. In binary, many decimal fractions cannot be represented exactly. As a result, `0.45` is stored as an approximate binary fraction in a `float`, and when this approximation is converted to a Decimal, the inexactness is preserved, can result in `0.450000000000000011102230246251565404236316680908203125`.

*[noncompliant01.py](noncompliant01.py):*

```py
"""Non-compliant Code Example"""

from decimal import Decimal

print(Decimal(0.45))
```

## Compliant Solution

In the `compliant01.py` code example, the floating-point value is passed as a string, allowing the value to be directly converted to a `Decimal` object with the exact decimal value. This is because the string representation is interpreted exactly as it appears, maintaining all the specified digits.

*[compliant01.py](compliant01.py):*

```py
"""Compliant Code Example"""

from decimal import Decimal

print(Decimal("0.45"))
```

## Related Guidelines

|||
|:---|:---|
|[SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java?src=breadcrumbs)|[NUM10-J. Do not construct BigDecimal objects from floating-point literals](https://wiki.sei.cmu.edu/confluence/display/java/NUM10-J.+Do+not+construct+BigDecimal+objects+from+floating-point+literals)|
|[MITRE CWE Base](http://cwe.mitre.org/)| [CWE-681](https://cwe.mitre.org/data/definitions/681.html)|
|[MITRE CWE Pillar](http://cwe.mitre.org/)|[CWE-664: Improper Control of a Resource Through its Lifetime](https://cwe.mitre.org/data/definitions/664.html)|

## Automated Detection

|Tool|Version|Checker|Description|
|:----|:----|:----|:----|
|[Bandit](https://bandit.readthedocs.io/en/latest/)|1.7.4 on python 3.10.4|Not Available||
|[Flake8](https://flake8.pycqa.org/en/latest/)|8-4.0.1 on python 3.10.4|Not Available||

## Biblography

|||
|:---|:---|
|[Wikipedia 2025](en.wikipedia.org)|IEEE 754 [online]. Available from: [https://en.wikipedia.org/wiki/IEEE_754](https://en.wikipedia.org/wiki/IEEE_754)|
|[Python docs](https://docs.python.org/3/)|decimal — Decimal fixed-point and floating-point arithmetic [online]. Available from: [https://docs.python.org/3/library/decimal.html](https://docs.python.org/3/library/decimal.html) [accessed 2 February 2025]|
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Compliant Code Example"""

from decimal import Decimal

print(Decimal("0.45"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Non-compliant Code Example"""

from decimal import Decimal

print(Decimal(0.45))
5 changes: 3 additions & 2 deletions docs/Secure-Coding-Guide-for-Python/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ It is __not production code__ and requires code-style or python best practices t
|[CWE-532: Insertion of Sensitive Information into Log File](CWE-664/CWE-532/README.md)|[CVE-2023-45585](https://www.cvedetails.com/cve/CVE-2023-45585),<br/>CVSSv3.1: __9.8__,<br/>EPSS: __0.04__ (01.11.2024)|
|[CWE-665: Improper Initialization](CWE-664/CWE-665/README.md)||
|[CWE-681: Incorrect Conversion between Numeric Types](CWE-664/CWE-681/README.md)||
|[CWE-681: Avoid an uncontrolled loss of precision when passing floating-point literals to a Decimal constructor.](CWE-664/CWE-681/01/README.md)||
|[CWE-833: Deadlock](CWE-664/CWE-833/README.md)||
|[CWE-843: Access of Resource Using Incompatible Type ('Type Confusion')](CWE-664/CWE-843/.)|[CVE-2021-29513](https://www.cvedetails.com/cve/CVE-2021-29513),<br/>CVSSv3.1: __7.8__,<br/>EPSS: __00.05__ (05.11.2024)|
|[XXX-005: Consider hash-based integrity verification of byte code files against their source code files](CWE-664/XXX-005/.)||
Expand All @@ -71,7 +72,7 @@ It is __not production code__ and requires code-style or python best practices t
|[CWE-693: Protection Mechanism Failure](https://cwe.mitre.org/data/definitions/693.html)|Prominent CVE|
|:----------------------------------------------------------------|:----|
|[CWE-184: Incomplete List of Disallowed Input](CWE-693/CWE-184/.)||
|[CWE-330: Use of Insufficiently Random Values](CWE-693/CWE-330/README.md)|[CVE-2020-7548](https://www.cvedetails.com/cve/CVE-2020-7548),<br/>CVSSv3.1: **9.8**,<br/>EPSS: **0.22** (12.12.2024)|
|[CWE-330: Use of Insufficiently Random Values](CWE-693/CWE-330/README.md)|[CVE-2020-7548](https://www.cvedetails.com/cve/CVE-2020-7548),<br/>CVSSv3.1: __9.8__,<br/>EPSS: __0.22__ (12.12.2024)|
|[CWE-798: Use of hardcoded credentials](CWE-693/CWE-798/.)||

|[CWE-697: Incorrect Comparison](https://cwe.mitre.org/data/definitions/703.html)|Prominent CVE|
Expand All @@ -98,7 +99,7 @@ It is __not production code__ and requires code-style or python best practices t
|:----------------------------------------------------------------|:----|
|[CWE-1095: Loop Condition Value Update within the Loop](CWE-710/CWE-1095/README.md)||
|[CWE-1109: Use of Same Variable for Multiple Purposes](CWE-710/CWE-1109/.)||
|[CWE-489: Active Debug Code](CWE-710/CWE-489/README.md)|[CVE-2018-14649](https://www.cvedetails.com/cve/CVE-2018-14649),<br/>CVSSv3.1: **9.8**,<br/>EPSS: **69.64** (12.12.2023)|
|[CWE-489: Active Debug Code](CWE-710/CWE-489/README.md)|[CVE-2018-14649](https://www.cvedetails.com/cve/CVE-2018-14649),<br/>CVSSv3.1: __9.8__,<br/>EPSS: __69.64__ (12.12.2023)|

## Biblography

Expand Down