Skip to content

Commit cc16bd3

Browse files
committed
do not chain exceptions to themselves
cpython actually makes sure the newly chained exception doesn't create a cycle (even indirectly); see _PyErr_SetObject use of "Floyd's cycle detection algo". We'll go for the simpler solution of just checking one level deep until it's clear we need to do more. Closes: #7414
1 parent 4cc7466 commit cc16bd3

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

py/vm.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ unwind_jump:;
11501150
mp_obj_t obj = mp_make_raise_obj(TOP());
11511151
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
11521152
mp_obj_t active_exception = get_active_exception(exc_sp, exc_stack);
1153-
if (active_exception != MP_OBJ_NULL) {
1153+
if (active_exception != MP_OBJ_NULL && active_exception != obj) {
11541154
mp_store_attr(obj, MP_QSTR___context__, active_exception);
11551155
}
11561156
#endif
@@ -1164,7 +1164,7 @@ unwind_jump:;
11641164
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
11651165
// search for the inner-most previous exception, to chain it
11661166
mp_obj_t active_exception = get_active_exception(exc_sp, exc_stack);
1167-
if (active_exception != MP_OBJ_NULL) {
1167+
if (active_exception != MP_OBJ_NULL && active_exception != obj) {
11681168
mp_store_attr(obj, MP_QSTR___context__, active_exception);
11691169
}
11701170
mp_store_attr(obj, MP_QSTR___cause__, cause);
@@ -1463,7 +1463,7 @@ unwind_jump:;
14631463
exc_sp->prev_exc = nlr.ret_val;
14641464
mp_obj_t obj = MP_OBJ_FROM_PTR(nlr.ret_val);
14651465
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
1466-
if (active_exception != MP_OBJ_NULL) {
1466+
if (active_exception != MP_OBJ_NULL && active_exception != obj) {
14671467
mp_store_attr(obj, MP_QSTR___context__, active_exception);
14681468
}
14691469
#endif

tests/circuitpython/traceback_test_chained.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,13 @@ def print_exc_info(e, chain=True):
6262
1 / 0
6363
except Exception as e:
6464
print_exc_info(e)
65+
66+
try:
67+
try:
68+
1 / 0
69+
except Exception as inner:
70+
raise inner
71+
except Exception as e:
72+
print_exc_info(e, chain=False)
73+
print_exc_info(e)
74+
print()

tests/circuitpython/traceback_test_chained.py.exp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,18 @@ Traceback (most recent call last):
5959
ZeroDivisionError: division by zero
6060
------------------------------------------------------------------------
6161

62+
------------------------------------------------------------------------
63+
Traceback (most recent call last):
64+
File "circuitpython/traceback_test_chained.py", line 70, in <module>
65+
File "circuitpython/traceback_test_chained.py", line 68, in <module>
66+
ZeroDivisionError: division by zero
67+
------------------------------------------------------------------------
68+
69+
------------------------------------------------------------------------
70+
Traceback (most recent call last):
71+
File "circuitpython/traceback_test_chained.py", line 70, in <module>
72+
File "circuitpython/traceback_test_chained.py", line 68, in <module>
73+
ZeroDivisionError: division by zero
74+
------------------------------------------------------------------------
75+
76+

0 commit comments

Comments
 (0)