Skip to content

Undefined behavior NULL + 0 in list_extend_{set,dict,dictitems} #133073

Closed
@picnixz

Description

@picnixz

Bug report

Found by @emmatyping.

Bug description:

This affects list_extend_{set,dict,dictitems}, e.g.:

static int
list_extend_set(PyListObject *self, PySetObject *other)
{
    Py_ssize_t m = Py_SIZE(self);
    Py_ssize_t n = PySet_GET_SIZE(other);
    if (list_resize(self, m + n) < 0) {
        return -1;
    }
    /* populate the end of self with iterable's items */
    Py_ssize_t setpos = 0;
    Py_hash_t hash;
    PyObject *key;
    PyObject **dest = self->ob_item + m; // UB if 'self' is the empty list!
    while (_PySet_NextEntryRef((PyObject *)other, &setpos, &key, &hash)) {
        FT_ATOMIC_STORE_PTR_RELEASE(*dest, key);
        dest++;
    }
    Py_SET_SIZE(self, m + n);
    return 0;
}

If a list object is empty, ob->ob_items will be NULL. In particular, list_resize won't allocate and the size will be 0. However:

PyObject **dest = self->ob_item + m;

becomes equivalent to NULL + 0 which is UB. There is no runtime error for now because the loop that follows is not executed.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Assignees

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