generated from ossf/project-template
-
Notifications
You must be signed in to change notification settings - Fork 184
pyDoc2GitHub Adding documentation for CWE-197 01 as part of #531 to GitHub #649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
104 changes: 104 additions & 0 deletions
104
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-197/01/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# CWE-197: Control rounding when converting to less precise numbers | ||
|
||
While defensive coding requires enforcing types, it is important to make conscious design decisions on how conversions are rounded. | ||
|
||
The `example01.py` code demonstrates how `int()` behaves differently to `round()`. | ||
|
||
[*example01.py:*](example01.py) | ||
|
||
```py | ||
""" Code Example """ | ||
|
||
print(int(0.5)) # prints 0 | ||
print(int(1.5)) # prints 1 | ||
print(int(1.45)) # prints 1 | ||
print(int(1.51)) # prints 1 | ||
print(int(-1.5)) # prints -1 | ||
|
||
print(round(0.5)) # prints 0 | ||
print(round(1.5)) # prints 2 | ||
print(round(1.45)) # prints 1 | ||
print(round(1.51)) # prints 2 | ||
print(round(-1.5)) # prints -2 | ||
|
||
print(type(round(0.5))) # prints <class 'int'> | ||
|
||
``` | ||
|
||
The build in `round()` does not allow to specify the type of rounding in use [[python round( ) 2024]](https://docs.python.org/3/library/functions.html#round). In Python 3 the `round()` function uses "bankers' rounding" (rounds to the nearest even number in case of ties). This is different to Python 2 which always rounds away from zero. Rounding provided by the `decimal` module allows a choice between 8 rounding modes [[python decimal 2024]](https://docs.python.org/3/library/decimal.html#rounding-modes). Rounding in mathematics and science is not discussed here as it requires a deeper knowledge of computer floating-point arithmetic's. | ||
|
||
## Non-Compliant Code Example (float to int) | ||
|
||
In `noncompliant01.py` there is no conscious choice of rounding mode. | ||
|
||
[*noncompliant01.py:*](noncompliant01.py) | ||
|
||
```py | ||
""" Non-compliant Code Example """ | ||
|
||
print(int(0.5)) # prints 0 | ||
print(int(1.5)) # prints 1 | ||
print(round(0.5)) # prints 0 | ||
print(round(1.5)) # prints 2 | ||
``` | ||
|
||
## Compliant Solution (float to int) | ||
|
||
Using the `Decimal` class from the `decimal` module allows more control over rounding by choosing one of the `8` rounding modes [[python decimal 2024]](https://docs.python.org/3/library/decimal.html#rounding-modes). | ||
|
||
[*compliant01.py:*](compliant01.py) | ||
|
||
```py | ||
""" Compliant Code Example """ | ||
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN | ||
|
||
print(Decimal("0.5").quantize(Decimal("1"), rounding=ROUND_HALF_UP)) # prints 1 | ||
print(Decimal("1.5").quantize(Decimal("1"), rounding=ROUND_HALF_UP)) # prints 2 | ||
print(Decimal("0.5").quantize(Decimal("1"), rounding=ROUND_HALF_DOWN)) # prints 0 | ||
print(Decimal("1.5").quantize(Decimal("1"), rounding=ROUND_HALF_DOWN)) # prints 1 | ||
``` | ||
|
||
The `.quantize(Decimal("1")`, determines the precision to be `integer` and `rounding=ROUND_HALF_UP` determines the type of rounding applied. Specifying numbers as strings avoids issues such as floating-point representations in binary. | ||
|
||
That `Decimal` can have unexpected results when operated without `Decimal.quantize()` on floating point numbers is demonstrated in `example02.py`. | ||
|
||
[*example02.py:*](example02.py) | ||
|
||
```py | ||
# SPDX-FileCopyrightText: OpenSSF project contributors | ||
# SPDX-License-Identifier: MIT | ||
""" Code Example """ | ||
from decimal import ROUND_HALF_UP, Decimal | ||
|
||
print(Decimal("0.10")) # prints 0.10 | ||
print(Decimal(0.10)) # prints 0.1000000000000000055511151231257827021181583404541015625 | ||
print(Decimal("0.10").quantize(Decimal("0.10"), rounding=ROUND_HALF_UP)) # prints 0.10 | ||
print(Decimal(0.10).quantize(Decimal("0.10"), rounding=ROUND_HALF_UP)) # prints 0.10 | ||
``` | ||
|
||
Initializing `Decimal` with an actual `float`, such as `0.10`, and without rounding creates an unprecise number `0.1000000000000000055511151231257827021181583404541015625` in `Python 3.9.2`. | ||
|
||
## Automated Detection | ||
|
||
|Tool|Version|Checker|Description| | ||
|:---|:---|:---|:---| | ||
|Bandit|1.7.4 on Python 3.10.4|Not Available|| | ||
|Flake8|8-4.0.1 on Python 3.10.4|Not Available|| | ||
|
||
## Related Guidelines | ||
|
||
||| | ||
|:---|:---| | ||
|[MITRE CWE](http://cwe.mitre.org/)|Pillar [CWE-682, Incorrect Conversion between Numeric Types (mitre.org)](http://cwe.mitre.org/data/definitions/682.html)| | ||
|[MITRE CWE](http://cwe.mitre.org/)|Class [CWE-197, Numeric Truncation Error](https://cwe.mitre.org/data/definitions/197.html)| | ||
|[SEI CERT C Coding Standard](https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard)|[INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data](https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data)| | ||
|[SEI CERT C Coding Standard](https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard)|[FLP34-C. Ensure that floating-point conversions are within range of the new type](https://wiki.sei.cmu.edu/confluence/display/c/FLP34-C.+Ensure+that+floating-point+conversions+are+within+range+of+the+new+type)| | ||
|[ISO/IEC TR 24772:2019](https://www.iso.org/standard/71091.html)|Programming languages — Guidance to avoiding vulnerabilities in programming languages, available from [https://www.iso.org/standard/71091.html](https://www.iso.org/standard/71091.html)| | ||
|[SEI CERT Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java)|[NUM12-J. Ensure conversions of numeric types to narrower types do not result in lost or misinterpreted data](https://wiki.sei.cmu.edu/confluence/display/java/NUM12-J.+Ensure+conversions+of+numeric+types+to+narrower+types+do+not+result+in+lost+or+misinterpreted+data)| | ||
|
||
## Biblography | ||
|
||
||| | ||
|:---|:---| | ||
|[python round( ) 2024](https://docs.python.org/3/library/functions.html#round)|python round( ), available from: [https://docs.python.org/3/library/functions.html#round](https://docs.python.org/3/library/functions.html#round), [Last accessed June 2024] | | ||
|[python decimal 2024](https://docs.python.org/3/library/decimal.html#rounding-modes)|Python decimal module, available from: [https://docs.python.org/3/library/decimal.html#rounding-modes](https://docs.python.org/3/library/decimal.html#rounding-modes)| |
9 changes: 6 additions & 3 deletions
9
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-197/01/compliant01.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
# SPDX-FileCopyrightText: OpenSSF project contributors | ||
# SPDX-License-Identifier: MIT | ||
""" Compliant Code Example """ | ||
foo = int(round(0.9)) | ||
type(foo) # class int | ||
print(foo) # prints 1 | ||
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN | ||
|
||
print(Decimal("0.5").quantize(Decimal("1"), rounding=ROUND_HALF_UP)) # prints 1 | ||
print(Decimal("1.5").quantize(Decimal("1"), rounding=ROUND_HALF_UP)) # prints 2 | ||
print(Decimal("0.5").quantize(Decimal("1"), rounding=ROUND_HALF_DOWN)) # prints 0 | ||
print(Decimal("1.5").quantize(Decimal("1"), rounding=ROUND_HALF_DOWN)) # prints 1 |
17 changes: 17 additions & 0 deletions
17
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-197/01/example01.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# SPDX-FileCopyrightText: OpenSSF project contributors | ||
# SPDX-License-Identifier: MIT | ||
""" Code Example """ | ||
|
||
print(int(0.5)) # prints 0 | ||
print(int(1.5)) # prints 1 | ||
print(int(1.45)) # prints 1 | ||
print(int(1.51)) # prints 1 | ||
print(int(-1.5)) # prints -1 | ||
|
||
print(round(0.5)) # prints 0 | ||
print(round(1.5)) # prints 2 | ||
print(round(1.45)) # prints 1 | ||
print(round(1.51)) # prints 2 | ||
print(round(-1.5)) # prints -2 | ||
|
||
print(type(round(0.5))) # prints <class 'int'> |
9 changes: 9 additions & 0 deletions
9
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-197/01/example02.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# SPDX-FileCopyrightText: OpenSSF project contributors | ||
# SPDX-License-Identifier: MIT | ||
""" Code Example """ | ||
from decimal import ROUND_HALF_UP, Decimal | ||
|
||
print(Decimal("0.10")) # prints 0.10 | ||
print(Decimal(0.10)) # prints 0.1000000000000000055511151231257827021181583404541015625 | ||
print(Decimal("0.10").quantize(Decimal("0.10"), rounding=ROUND_HALF_UP)) # prints 0.10 | ||
print(Decimal(0.10).quantize(Decimal("0.10"), rounding=ROUND_HALF_UP)) # prints 0.10 |
8 changes: 5 additions & 3 deletions
8
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-197/01/noncompliant01.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
# SPDX-FileCopyrightText: OpenSSF project contributors | ||
# SPDX-License-Identifier: MIT | ||
""" Non-compliant Code Example """ | ||
foo = int(0.9) | ||
type(foo) # class int | ||
print(foo) # prints 0 | ||
|
||
print(int(0.5)) # prints 0 | ||
print(int(1.5)) # prints 1 | ||
print(round(0.5)) # prints 0 | ||
print(round(1.5)) # prints 2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cosmetics: license comments in the Markdown code