Author meador.inge
Recipients amaury.forgeotdarc, belopolsky, meador.inge, skrah
Date 2011-10-03.00:22:14
SpamBayes Score 0.000757125
Marked as misclassified No
Message-id <1317601335.6.0.176142368064.issue13091@psf.upfronthosting.co.za>
In-reply-to
Content
> this pointer is tied to a CDataObject; its tp_alloc should free the 
> memory

The free in 'PyCData_clear' is conditional:

    if ((self->b_needsfree)
        && ((size_t)dict->size > sizeof(self->b_value)))
        PyMem_Free(self->b_ptr);

As written, 'PyCData_clear' has no way of knowing that memory has been 
{m,re}alloc'd in 'resize'.  So in some cases memory will leak.  Here is 
a small reproduction case extracted from 'test_varsize_struct.py'.

    from ctypes import *

    class X(Structure):
        _fields_ = [("item", c_int),
                    ("array", c_int * 1)]

    x = X()
    x.item = 42
    x.array[0] = 100
    new_size = sizeof(X) + sizeof(c_int) * 5
    resize(x, new_size)

One potential fix is:

diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -2440,7 +2440,7 @@ PyCData_clear(CDataObject *self)
     assert(dict); /* Cannot be NULL for CDataObject instances */
     Py_CLEAR(self->b_objects);
     if ((self->b_needsfree)
-        && ((size_t)dict->size > sizeof(self->b_value)))
+        && (self->b_ptr != (char *)&self->b_value))
         PyMem_Free(self->b_ptr);
     self->b_ptr = NULL;
     Py_CLEAR(self->b_base);

I need to think about that more, though.
History
Date User Action Args
2011-10-03 00:22:15meador.ingesetrecipients: + meador.inge, amaury.forgeotdarc, belopolsky, skrah
2011-10-03 00:22:15meador.ingesetmessageid: <1317601335.6.0.176142368064.issue13091@psf.upfronthosting.co.za>
2011-10-03 00:22:15meador.ingelinkissue13091 messages
2011-10-03 00:22:14meador.ingecreate