Commit 1505e3e3 authored by Jeremy Hylton's avatar Jeremy Hylton

Fix memory leak in BTrees.

The Mapping_update() method iterated over a sequence of 2-tuples, but
held an extra reference to the sequence.  The sequence object was
DECREFed on an error exit but not on the normal return.

The fix reworks the control flow of the function to make the reference
counting behavior a little clearer:

   - Test for call with no arguments and return immediately if so.

   - If the argument is a sequence, don't INCREF it.

   - If the argument passed isn't a sequence, call its items() method
     and store the result in the local variables seq and items.

   - On exit, do Py_XDECREF(items).  This will do a decref only if a
     the second case above applied.

Two other minor nits:

   - Make consistent use of spaces around = in assignments (as opposed
     to a fix of both)

   - Remove assignment from conditional expression.
parent 5dabe9c3
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
****************************************************************************/ ****************************************************************************/
#define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.19 2001/10/19 18:55:09 andreasjung Exp $\n" #define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.20 2001/10/31 19:19:38 jeremy Exp $\n"
/* /*
** _bucket_get ** _bucket_get
...@@ -338,59 +338,69 @@ bucket_setitem(Bucket *self, PyObject *key, PyObject *v) ...@@ -338,59 +338,69 @@ bucket_setitem(Bucket *self, PyObject *key, PyObject *v)
return 0; return 0;
} }
/**
** Mapping_update()
**
** Accepts a sequence of 2-tuples or any object with an items()
** method that returns a sequence of 2-tuples.
**
*/
static PyObject * static PyObject *
Mapping_update(PyObject *self, PyObject *args) Mapping_update(PyObject *self, PyObject *args)
{ {
PyObject *seq=0, *o, *t, *v, *tb, *k; PyObject *seq=0, *o, *t, *v, *tb, *k, *items = NULL;
int i, ind; int i, ind;
UNLESS(PyArg_ParseTuple(args, "|O:update", &seq)) return NULL; UNLESS(PyArg_ParseTuple(args, "|O:update", &seq)) return NULL;
if (seq) if (!seq)
{
Py_INCREF(Py_None);
return Py_None;
}
if (!PySequence_Check(seq))
{ {
items = PyObject_GetAttr(seq, items_str);
UNLESS(items) return NULL;
ASSIGN(items, PyObject_CallObject(items, NULL));
UNLESS(items) return NULL;
/* items is DECREFed on exit, seq is not */
seq = items;
}
if (PySequence_Check(seq)) for (i=0; ; i++)
{ {
Py_INCREF(seq); o = PySequence_GetItem(seq, i);
} UNLESS (o)
{
PyErr_Fetch(&t, &v, &tb);
if (t != PyExc_IndexError)
{
PyErr_Restore(t, v, tb);
goto err;
}
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
break;
}
ind = PyArg_ParseTuple(o, "OO;items must be 2-item tuples", &k, &v);
if (ind)
ind = PyObject_SetItem(self, k, v);
else else
{ ind = -1;
seq=PyObject_GetAttr(seq, items_str); Py_DECREF(o);
UNLESS(seq) return NULL; if (ind < 0) goto err;
ASSIGN(seq, PyObject_CallObject(seq, NULL));
UNLESS(seq) return NULL;
}
for (i=0; ; i++)
{
UNLESS (o=PySequence_GetItem(seq, i))
{
PyErr_Fetch(&t, &v, &tb);
if (t != PyExc_IndexError)
{
PyErr_Restore(t, v, tb);
goto err;
}
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
break;
}
ind=PyArg_ParseTuple(o, "OO;items must be 2-item tuples", &k, &v);
if (ind)
ind = PyObject_SetItem(self, k, v);
else
ind=-1;
Py_DECREF(o);
if (ind < 0) goto err;
}
} }
Py_XDECREF(items);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
err: err:
Py_DECREF(seq); Py_XDECREF(items);
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment