Skip to content

Commit 3e771c5

Browse files
author
Andrew Costello
committed
CWE-584
1 parent 826e033 commit 3e771c5

File tree

4 files changed

+173
-0
lines changed

4 files changed

+173
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# CWE-584: Return Inside Finally Block
2+
3+
Do not use `return` , `break` or `continue` statements in a try-finally block, as the exception will not be processed. The Python documentation [[Python 3.9]](https://docs.python.org/3.9/reference/compound_stmts.html#finally) notes, "If the `finally` clause executes a [`return`](https://docs.python.org/3.9/reference/simple_stmts.html#return) , [`break`](https://docs.python.org/3.9/reference/simple_stmts.html#break) or [`continue`](https://docs.python.org/3.9/reference/simple_stmts.html#continue) statement, the saved exception is discarded."
4+
5+
## Non-Compliant Code Example
6+
7+
The `return` statement is within the finally block, which means the exception will have no effect.
8+
9+
*[noncompliant01.py](noncompliant01.py):*
10+
11+
```python
12+
# SPDX-FileCopyrightText: OpenSSF project contributors
13+
# SPDX-License-Identifier: MIT
14+
15+
""" Non-compliant Code Example """
16+
17+
18+
def do_logic():
19+
try:
20+
raise Exception
21+
finally:
22+
print("logic done")
23+
return True
24+
25+
26+
#####################
27+
# exploiting above code example
28+
#####################
29+
do_logic()
30+
```
31+
32+
This code sample will print: `logic done`.
33+
34+
## Compliant Solution
35+
36+
The `return` statement has been moved to the end of the method, so the code sample will successfully raise the exception.
37+
38+
*[compliant01.py](compliant01.py):*
39+
40+
```python
41+
# SPDX-FileCopyrightText: OpenSSF project contributors
42+
# SPDX-License-Identifier: MIT
43+
44+
""" Compliant Code Example """
45+
46+
47+
def do_logic():
48+
try:
49+
raise Exception
50+
finally:
51+
print("logic done")
52+
# return statement goes here
53+
# when exception is raised conditionally
54+
return True
55+
56+
57+
#####################
58+
# exploiting above code example
59+
#####################
60+
do_logic()
61+
```
62+
63+
## Compliant Solution - `break` inside a loop
64+
65+
It is permissible to use control flow statements that lead into a finally block, as long as they do not attempt to exit from within it. For example, the following code complies with this rule because the break statement is used to exit a while loop and does not attempt to break out of the finally block itself.
66+
67+
*[compliant02.py](compliant02.py):*
68+
69+
```python
70+
# SPDX-FileCopyrightText: OpenSSF project contributors
71+
# SPDX-License-Identifier: MIT
72+
73+
def do_logic():
74+
try:
75+
raise Exception
76+
finally:
77+
c = 0
78+
while c < 5:
79+
print(f"c is {c}")
80+
c += 1
81+
if c == 3:
82+
break
83+
# return statement goes here
84+
# when exception is raised conditionally
85+
return True
86+
87+
88+
#####################
89+
# exploiting above code example
90+
#####################
91+
do_logic()
92+
```
93+
94+
## Automated Detection
95+
96+
|Tool|Version|Checker|Description|
97+
|:----|:----|:----|:----|
98+
|[Pylint](https://pylint.pycqa.org/)|3.3.4|W0150|return statement in finally block may swallow exception (lost-exception)|
99+
|[Pylint](https://pylint.pycqa.org/)|3.3.4|W0134|'return' shadowed by the 'finally' clause.|
100+
101+
## Related Guidelines
102+
103+
|||
104+
|:---|:---|
105+
|[SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java?src=breadcrumbs)|[ERR04-J. Do not complete abruptly from a finally block - SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/ERR04-J.+Do+not+complete+abruptly+from+a+finally+block)|
106+
|[MITRE CWE](http://cwe.mitre.org/)|[CWE-459, Incomplete Cleanup](http://cwe.mitre.org/data/definitions/459.html)|
107+
|[MITRE CWE](http://cwe.mitre.org/)|[CWE-584, Return Inside finally Block](http://cwe.mitre.org/data/definitions/584.html)|
108+
109+
## Bibliography
110+
111+
|||
112+
|:---|:---|
113+
|[[Python 3.9]](https://docs.python.org/3.9/reference/compound_stmts.html#finally)|[Compound statements — Python 3.9.13 documentation](https://docs.python.org/3.9/reference/compound_stmts.html#finally)|
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# SPDX-FileCopyrightText: OpenSSF project contributors
2+
# SPDX-License-Identifier: MIT
3+
4+
"""Compliant Code Example"""
5+
6+
7+
def do_logic():
8+
try:
9+
raise Exception
10+
finally:
11+
print("logic done")
12+
# return statement goes here
13+
# when exception is raised conditionally
14+
return True
15+
16+
17+
#####################
18+
# exploiting above code example
19+
#####################
20+
do_logic()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-FileCopyrightText: OpenSSF project contributors
2+
# SPDX-License-Identifier: MIT
3+
4+
def do_logic():
5+
try:
6+
raise Exception
7+
finally:
8+
c = 0
9+
while c < 5:
10+
print(f"c is {c}")
11+
c += 1
12+
if c == 3:
13+
break
14+
# return statement goes here
15+
# when exception is raised conditionally
16+
return True
17+
18+
19+
#####################
20+
# exploiting above code example
21+
#####################
22+
do_logic()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SPDX-FileCopyrightText: OpenSSF project contributors
2+
# SPDX-License-Identifier: MIT
3+
4+
"""Non-compliant Code Example"""
5+
6+
7+
def do_logic():
8+
try:
9+
raise Exception
10+
finally:
11+
print("logic done")
12+
return True
13+
14+
15+
#####################
16+
# exploiting above code example
17+
#####################
18+
do_logic()

0 commit comments

Comments
 (0)