Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on Feb 13, 2025. It is now read-only.
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

slpmodule_new() doesn't initialize extra members added by type_new() #22

Copy link
Copy link
Closed
@ghost

Description

Originally reported by: RMTEW FULL NAME (Bitbucket: rmtew, GitHub: rmtew)


(originally reported in Trac by ndade on 2013-06-08 02:47:27)

slpmodule_new() allocates the module using

        m = PyObject_GC_New(PySlpModuleObject, PySlpModule_TypePtr);

and that uses PySlpModule_TypePtr->tp_basicsize to determine how many bytes to allocate. On amd64, for example, we expect there to be 40 bytes allocated (sizeof(*m)), but in fact 48 are allocated[1] because tp_basicsize was set to 48 back when the SLP module type was derived in flextype.c. type_new() computed 48 by taking the base type's tp_basicsize of 40 and adding space for one more pointer to hold the weak reference list. Grep for "may_add_weak" in type_new() for the details.

Since this silently added field in *m is not initialized, when the slpmodule object is cleaned up during exit, if that field had a non-NULL value that value gets interpreted as the head of a list of PyWeakReference objects and garbage ensues.

Apparently with the default memory allocators, and perhaps since slpmodule is allocated pretty early, it was NULL. But I've been replacing the GC allocator with my own and there the memory was recycled and the pointer was non-NULL.

The fix is to init the entire memory/object allocated. Something like

@@ -806,6 +806,8 @@
        m->__tasklet__ = NULL;
        nameobj = PyString_FromString(name);
        m->md_dict = PyDict_New();
+        // set the extra fields to 0 (type_new() added a weak reference list field automatically)
+        memset(m+1, 0, PySlpModule_TypePtr->tp_basicsize - sizeof(*m));
        if (m->md_dict == NULL || nameobj == NULL)
                goto fail;
        if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)

does the trick.

You can also reproduce this by making the base memory allocator memset() the memory to random values.

[1] 48 is not including the Py_GC_Head header, which adds another 24 or 32 bytes depending on alignment requirements.


Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.