|
3 | 3 | #define PY_SSIZE_T_CLEAN |
4 | 4 | #include "Python.h" |
5 | 5 | #include "pycore_long.h" // _PyLong_GetZero() |
| 6 | +#include "pycore_object.h" // _PyObject_GC_TRACK() |
6 | 7 | #include "pycore_tuple.h" // _PyTuple_ITEMS() |
7 | 8 | #include <stddef.h> // offsetof() |
8 | 9 |
|
@@ -2378,6 +2379,11 @@ product_next(productobject *lz) |
2378 | 2379 | lz->result = result; |
2379 | 2380 | Py_DECREF(old_result); |
2380 | 2381 | } |
| 2382 | + // bpo-42536: The GC may have untracked this result tuple. Since we're |
| 2383 | + // recycling it, make sure it's tracked again: |
| 2384 | + else if (!_PyObject_GC_IS_TRACKED(result)) { |
| 2385 | + _PyObject_GC_TRACK(result); |
| 2386 | + } |
2381 | 2387 | /* Now, we've got the only copy so we can update it in-place */ |
2382 | 2388 | assert (npools==0 || Py_REFCNT(result) == 1); |
2383 | 2389 |
|
@@ -2701,6 +2707,11 @@ combinations_next(combinationsobject *co) |
2701 | 2707 | co->result = result; |
2702 | 2708 | Py_DECREF(old_result); |
2703 | 2709 | } |
| 2710 | + // bpo-42536: The GC may have untracked this result tuple. Since we're |
| 2711 | + // recycling it, make sure it's tracked again: |
| 2712 | + else if (!_PyObject_GC_IS_TRACKED(result)) { |
| 2713 | + _PyObject_GC_TRACK(result); |
| 2714 | + } |
2704 | 2715 | /* Now, we've got the only copy so we can update it in-place |
2705 | 2716 | * CPython's empty tuple is a singleton and cached in |
2706 | 2717 | * PyTuple's freelist. |
@@ -3035,6 +3046,11 @@ cwr_next(cwrobject *co) |
3035 | 3046 | co->result = result; |
3036 | 3047 | Py_DECREF(old_result); |
3037 | 3048 | } |
| 3049 | + // bpo-42536: The GC may have untracked this result tuple. Since we're |
| 3050 | + // recycling it, make sure it's tracked again: |
| 3051 | + else if (!_PyObject_GC_IS_TRACKED(result)) { |
| 3052 | + _PyObject_GC_TRACK(result); |
| 3053 | + } |
3038 | 3054 | /* Now, we've got the only copy so we can update it in-place CPython's |
3039 | 3055 | empty tuple is a singleton and cached in PyTuple's freelist. */ |
3040 | 3056 | assert(r == 0 || Py_REFCNT(result) == 1); |
@@ -3379,6 +3395,11 @@ permutations_next(permutationsobject *po) |
3379 | 3395 | po->result = result; |
3380 | 3396 | Py_DECREF(old_result); |
3381 | 3397 | } |
| 3398 | + // bpo-42536: The GC may have untracked this result tuple. Since we're |
| 3399 | + // recycling it, make sure it's tracked again: |
| 3400 | + else if (!_PyObject_GC_IS_TRACKED(result)) { |
| 3401 | + _PyObject_GC_TRACK(result); |
| 3402 | + } |
3382 | 3403 | /* Now, we've got the only copy so we can update it in-place */ |
3383 | 3404 | assert(r == 0 || Py_REFCNT(result) == 1); |
3384 | 3405 |
|
@@ -4649,6 +4670,11 @@ zip_longest_next(ziplongestobject *lz) |
4649 | 4670 | PyTuple_SET_ITEM(result, i, item); |
4650 | 4671 | Py_DECREF(olditem); |
4651 | 4672 | } |
| 4673 | + // bpo-42536: The GC may have untracked this result tuple. Since we're |
| 4674 | + // recycling it, make sure it's tracked again: |
| 4675 | + if (!_PyObject_GC_IS_TRACKED(result)) { |
| 4676 | + _PyObject_GC_TRACK(result); |
| 4677 | + } |
4652 | 4678 | } else { |
4653 | 4679 | result = PyTuple_New(tuplesize); |
4654 | 4680 | if (result == NULL) |
|
0 commit comments