Fix memory leak in C implementation of sorted_tree_items.
authorDave Borowitz <dborowitz@google.com>
Tue, 4 May 2010 21:54:05 +0000 (14:54 -0700)
committerDave Borowitz <dborowitz@google.com>
Mon, 24 May 2010 17:19:57 +0000 (10:19 -0700)
The tuples created by PyTuple_Pack did not have their refcounts
decreased before raising an exception.

Change-Id: Ic7b62c0fb008129d648d2c3bacfbc2d47260229b

NEWS
dulwich/_objects.c

diff --git a/NEWS b/NEWS
index 86d57462e6df18d70287a8303af1afa6865f6ed3..75dcb265b564d95b918507012117fdfed30eaf72 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
 0.6.1  UNRELEASED
 
+ BUG FIXES
+
+  * Fix memory leak in C implementation of sorted_tree_items. (Dave Borowitz)
+
  TESTS
 
   * Add tests for sorted_tree_items and C implementation. (Dave Borowitz)
index 149c8a6e92386f0ec37fca57d71953b76de239bf..7f992b70687a75c578ed3e1b0006601db4605308 100644 (file)
@@ -136,6 +136,14 @@ int cmp_tree_item(const void *_a, const void *_b)
        return strcmp(remain_a, remain_b);
 }
 
+static void free_tree_items(struct tree_item *items, int num) {
+       int i;
+       for (i = 0; i < num; i++) {
+               Py_DECREF(items[i].tuple);
+       }
+       free(items);
+}
+
 static PyObject *py_sorted_tree_items(PyObject *self, PyObject *entries)
 {
        struct tree_item *qsort_entries;
@@ -162,13 +170,13 @@ static PyObject *py_sorted_tree_items(PyObject *self, PyObject *entries)
 
                if (!PyString_Check(key)) {
                        PyErr_SetString(PyExc_TypeError, "Name is not a string");
-                       free(qsort_entries);
+                       free_tree_items(qsort_entries, i);
                        return NULL;
                }
 
                if (PyTuple_Size(value) != 2) {
                        PyErr_SetString(PyExc_ValueError, "Tuple has invalid size");
-                       free(qsort_entries);
+                       free_tree_items(qsort_entries, i);
                        return NULL;
                }
 
@@ -176,19 +184,21 @@ static PyObject *py_sorted_tree_items(PyObject *self, PyObject *entries)
                py_int_mode = PyNumber_Int(py_mode);
                if (!py_int_mode) {
                        PyErr_SetString(PyExc_TypeError, "Mode is not an integral type");
-                       free(qsort_entries);
+                       free_tree_items(qsort_entries, i);
                        return NULL;
                }
 
                py_sha = PyTuple_GET_ITEM(value, 1);
                if (!PyString_Check(py_sha)) {
                        PyErr_SetString(PyExc_TypeError, "SHA is not a string");
-                       free(qsort_entries);
+                       Py_DECREF(py_int_mode);
+                       free_tree_items(qsort_entries, i);
                        return NULL;
                }
                qsort_entries[i].name = PyString_AS_STRING(key);
                qsort_entries[i].mode = PyInt_AS_LONG(py_mode);
-               qsort_entries[i].tuple = PyTuple_Pack(3, key, py_mode, py_sha);
+               qsort_entries[i].tuple = PyTuple_Pack(3, key, py_int_mode, py_sha);
+               Py_DECREF(py_int_mode);
                i++;
        }
 
@@ -196,7 +206,7 @@ static PyObject *py_sorted_tree_items(PyObject *self, PyObject *entries)
 
        ret = PyList_New(num);
        if (ret == NULL) {
-               free(qsort_entries);
+               free_tree_items(qsort_entries, i);
                PyErr_NoMemory();
                return NULL;
        }