Skip to content

Callable iterator can SystemError if call exhausts the iterator #101892

Closed
@ionite34

Description

@ionite34

Bug report

If the callable of a callable iterator (with sentinel) exhausts the iterator itself during the call, a SystemError occurs.

Example discovered by @chilaxan

def bug():
    if bug.clear:
        return 1
    else:
        bug.clear = True
        list(bug.iterator)
        return 0

bug.iterator = iter(bug, 1)
bug.clear = False
next(bug.iterator)
SystemError: Objects\object.c:722: bad argument to internal function

Likely cause

iterobject.calliter_iternext does not check whether it->it_sentinel is NULL after the _PyObject_CallNoArgs call
https://github.com/python/cpython/blob/main/Objects/iterobject.c#L207-L237

static PyObject *
calliter_iternext(calliterobject *it)
{
    PyObject *result;

    if (it->it_callable == NULL) {
        return NULL;
    }

+   result = _PyObject_CallNoArgs(it->it_callable);
    if (result != NULL) {
        int ok;

+       ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
        if (ok == 0) {
            return result; /* Common case, fast path */
        }
(...)

Your environment

Appears to affect 3.7-3.12

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions