summaryrefslogtreecommitdiffstats
path: root/Lib/unittest/result.py
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-12-04 19:58:31 (GMT)
committerGitHub <noreply@github.com>2022-12-04 19:58:31 (GMT)
commite699e5c20fc495952905597edfa82de0c1848f8c (patch)
tree1be944629ed9854a163b6050bef883a7caa60ab3 /Lib/unittest/result.py
parentac781282712ab39cd6339e3c780c11e0027d22ab (diff)
downloadcpython-e699e5c20fc495952905597edfa82de0c1848f8c.zip
cpython-e699e5c20fc495952905597edfa82de0c1848f8c.tar.gz
cpython-e699e5c20fc495952905597edfa82de0c1848f8c.tar.bz2
gh-98458: unittest: bugfix for infinite loop while handling chained exceptions that contain cycles (GH-98459)
* Bugfix addressing infinite loop while handling self-referencing chained exception in TestResult._clean_tracebacks() * Bugfix extended to properly handle exception cycles in _clean_tracebacks. The "seen" set follows the approach used in the TracebackException class (thank you @iritkatriel for pointing it out) * adds a test for a single chained exception that holds a self-loop in its __cause__ and __context__ attributes (cherry picked from commit 72ec518203c3f3577a5e888b12f10bb49060e6c2) Co-authored-by: AlexTate <0xalextate@gmail.com>
Diffstat (limited to 'Lib/unittest/result.py')
-rw-r--r--Lib/unittest/result.py4
1 files changed, 3 insertions, 1 deletions
diff --git a/Lib/unittest/result.py b/Lib/unittest/result.py
index 3da7005..5ca4c23 100644
--- a/Lib/unittest/result.py
+++ b/Lib/unittest/result.py
@@ -196,6 +196,7 @@ class TestResult(object):
ret = None
first = True
excs = [(exctype, value, tb)]
+ seen = {id(value)} # Detect loops in chained exceptions.
while excs:
(exctype, value, tb) = excs.pop()
# Skip test runner traceback levels
@@ -214,8 +215,9 @@ class TestResult(object):
if value is not None:
for c in (value.__cause__, value.__context__):
- if c is not None:
+ if c is not None and id(c) not in seen:
excs.append((type(c), c, c.__traceback__))
+ seen.add(id(c))
return ret
def _is_relevant_tb_level(self, tb):