mirror of https://github.com/astral-sh/ruff
[`pylint`] Fix `unreachable` infinite loop (`PLW0101`) (#15278)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary Fix infinite loop issue reported here #15248. The issue was caused by the break inside the if block, which caused the flow to exit in an unforeseen way. This caused other issues, eventually leading to an infinite loop. Resolves #15248. Resolves #15336. ## Test Plan Added failing code to fixture. --------- Co-authored-by: Micha Reiser <micha@reiser.io> Co-authored-by: dylwil3 <dylwil3@gmail.com>
This commit is contained in:
parent
7284d68157
commit
450d4e0e0c
|
|
@ -116,3 +116,15 @@ def func():
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
raise Exception("other")
|
raise Exception("other")
|
||||||
|
|
||||||
|
# previously caused infinite loop
|
||||||
|
# found by fuzzer
|
||||||
|
def func():
|
||||||
|
for i in():
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
while r:
|
||||||
|
if t:break
|
||||||
|
finally:()
|
||||||
|
return
|
||||||
|
except:l
|
||||||
|
|
|
||||||
|
|
@ -145,3 +145,12 @@ def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
|
||||||
port += 1
|
port += 1
|
||||||
|
|
||||||
self.thread = threading.Thread(target=self._run_web_server)
|
self.thread = threading.Thread(target=self._run_web_server)
|
||||||
|
|
||||||
|
def func():
|
||||||
|
while T:
|
||||||
|
try:
|
||||||
|
while():
|
||||||
|
if 3:
|
||||||
|
break
|
||||||
|
finally:
|
||||||
|
return
|
||||||
|
|
|
||||||
|
|
@ -708,3 +708,76 @@ flowchart TD
|
||||||
block1 --> return
|
block1 --> return
|
||||||
block0 --> return
|
block0 --> return
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Function 13
|
||||||
|
### Source
|
||||||
|
```python
|
||||||
|
def func():
|
||||||
|
for i in():
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
while r:
|
||||||
|
if t:break
|
||||||
|
finally:()
|
||||||
|
return
|
||||||
|
except:l
|
||||||
|
```
|
||||||
|
|
||||||
|
### Control Flow Graph
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
start(("Start"))
|
||||||
|
return(("End"))
|
||||||
|
block0[["`*(empty)*`"]]
|
||||||
|
block1[["Loop continue"]]
|
||||||
|
block2["return\n"]
|
||||||
|
block3["()\n"]
|
||||||
|
block4[["Loop continue"]]
|
||||||
|
block5["break\n"]
|
||||||
|
block6["if t:break\n"]
|
||||||
|
block7["while r:
|
||||||
|
if t:break\n"]
|
||||||
|
block8[["Exception raised"]]
|
||||||
|
block9["try:
|
||||||
|
while r:
|
||||||
|
if t:break
|
||||||
|
finally:()\n"]
|
||||||
|
block10[["Exception raised"]]
|
||||||
|
block11["l\n"]
|
||||||
|
block12["try:
|
||||||
|
try:
|
||||||
|
while r:
|
||||||
|
if t:break
|
||||||
|
finally:()
|
||||||
|
return
|
||||||
|
except:l\n"]
|
||||||
|
block13["for i in():
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
while r:
|
||||||
|
if t:break
|
||||||
|
finally:()
|
||||||
|
return
|
||||||
|
except:l\n"]
|
||||||
|
|
||||||
|
start --> block13
|
||||||
|
block13 -- "()" --> block12
|
||||||
|
block13 -- "else" --> block0
|
||||||
|
block12 -- "Exception raised" --> block11
|
||||||
|
block12 -- "else" --> block9
|
||||||
|
block11 --> block1
|
||||||
|
block10 --> return
|
||||||
|
block9 -- "Exception raised" --> block8
|
||||||
|
block9 -- "else" --> block7
|
||||||
|
block8 --> block3
|
||||||
|
block7 -- "r" --> block6
|
||||||
|
block7 -- "else" --> block3
|
||||||
|
block6 -- "t" --> block5
|
||||||
|
block6 -- "else" --> block4
|
||||||
|
block5 --> block3
|
||||||
|
block4 --> block7
|
||||||
|
block3 --> block2
|
||||||
|
block2 --> return
|
||||||
|
block1 --> block13
|
||||||
|
block0 --> return
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -777,3 +777,63 @@ flowchart TD
|
||||||
block1 --> block7
|
block1 --> block7
|
||||||
block0 --> return
|
block0 --> return
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Function 23
|
||||||
|
### Source
|
||||||
|
```python
|
||||||
|
def func():
|
||||||
|
while T:
|
||||||
|
try:
|
||||||
|
while():
|
||||||
|
if 3:
|
||||||
|
break
|
||||||
|
finally:
|
||||||
|
return
|
||||||
|
```
|
||||||
|
|
||||||
|
### Control Flow Graph
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
start(("Start"))
|
||||||
|
return(("End"))
|
||||||
|
block0[["`*(empty)*`"]]
|
||||||
|
block1[["Loop continue"]]
|
||||||
|
block2["return\n"]
|
||||||
|
block3[["Loop continue"]]
|
||||||
|
block4["break\n"]
|
||||||
|
block5["if 3:
|
||||||
|
break\n"]
|
||||||
|
block6["while():
|
||||||
|
if 3:
|
||||||
|
break\n"]
|
||||||
|
block7[["Exception raised"]]
|
||||||
|
block8["try:
|
||||||
|
while():
|
||||||
|
if 3:
|
||||||
|
break
|
||||||
|
finally:
|
||||||
|
return\n"]
|
||||||
|
block9["while T:
|
||||||
|
try:
|
||||||
|
while():
|
||||||
|
if 3:
|
||||||
|
break
|
||||||
|
finally:
|
||||||
|
return\n"]
|
||||||
|
|
||||||
|
start --> block9
|
||||||
|
block9 -- "T" --> block8
|
||||||
|
block9 -- "else" --> block0
|
||||||
|
block8 -- "Exception raised" --> block7
|
||||||
|
block8 -- "else" --> block6
|
||||||
|
block7 --> block2
|
||||||
|
block6 -- "()" --> block5
|
||||||
|
block6 -- "else" --> block2
|
||||||
|
block5 -- "3" --> block4
|
||||||
|
block5 -- "else" --> block3
|
||||||
|
block4 --> block2
|
||||||
|
block3 --> block6
|
||||||
|
block2 --> return
|
||||||
|
block1 --> block9
|
||||||
|
block0 --> return
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -462,6 +462,7 @@ fn post_process_loop(
|
||||||
Some(Stmt::Continue(_)) => {
|
Some(Stmt::Continue(_)) => {
|
||||||
block.next = NextBlock::Always(loop_start);
|
block.next = NextBlock::Always(loop_start);
|
||||||
}
|
}
|
||||||
|
Some(Stmt::Return(_)) => return,
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
idx = next;
|
idx = next;
|
||||||
|
|
@ -603,6 +604,7 @@ fn post_process_try(
|
||||||
NextBlock::Always(next) => {
|
NextBlock::Always(next) => {
|
||||||
next_index = *next;
|
next_index = *next;
|
||||||
match block.stmts.last() {
|
match block.stmts.last() {
|
||||||
|
Some(Stmt::Break(_)) => return,
|
||||||
Some(Stmt::Continue(_)) => return,
|
Some(Stmt::Continue(_)) => return,
|
||||||
Some(Stmt::Raise(_)) => {
|
Some(Stmt::Raise(_)) => {
|
||||||
// re-route to except if not already re-routed
|
// re-route to except if not already re-routed
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue