Decrement references to python objects passed to Py_BuildValue
authorNoel Power <noel.power@suse.com>
Tue, 22 Jan 2019 18:26:23 +0000 (18:26 +0000)
committerNoel Power <npower@samba.org>
Thu, 7 Feb 2019 12:44:30 +0000 (13:44 +0100)
Py_BuildValue when processing format 'O' will
  'Pass a Python object untouched (except for its reference count,
   which is incremented by one'

Basically this means if you are using a new reference to a PyObject
to pass to BuildValue (to be used with the 'O' format) the reference
*isn't* stolen so you really do need to DECREF it in order to ensure
it gets cleaned up.

Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
auth/credentials/pycredentials.c
lib/ldb/pyldb.c
source3/libsmb/pylibsmb.c
source4/dns_server/pydns.c

index d1ee12e45a953d23eafc0bdb665bbc973297bdcd..1b86e0015573bf6fdb652f40bae28a9401abfc62 100644 (file)
@@ -75,9 +75,10 @@ static PyObject *py_creds_get_ntlm_username_domain(PyObject *self, PyObject *unu
        PyObject *ret = NULL;
        cli_credentials_get_ntlm_username_domain(PyCredentials_AsCliCredentials(self),
                                                 frame, &user, &domain);
-       ret = Py_BuildValue("(OO)",
-                           PyString_FromStringOrNULL(user),
-                           PyString_FromStringOrNULL(domain));
+       ret = Py_BuildValue("(ss)",
+                           user,
+                           domain);
+
        TALLOC_FREE(frame);
        return ret;
 }
index 8e48fa5d56dc36e319a59825806145a8bba1549e..a4618db8d35e214e525f56e311eafb4e7b150cd5 100644 (file)
@@ -1673,9 +1673,13 @@ static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
                Py_RETURN_NONE;
        } else {
        /* We don't want this attached to the 'ldb' any more */
-               return Py_BuildValue(discard_const_p(char, "(iO)"),
-                                    ldif->changetype,
-                                    PyLdbMessage_FromMessage(ldif->msg));
+               PyObject *obj = PyLdbMessage_FromMessage(ldif->msg);
+               PyObject *result =
+                       Py_BuildValue(discard_const_p(char, "(iO)"),
+                                     ldif->changetype,
+                                     obj);
+               Py_CLEAR(obj);
+               return result;
        }
 }
 
@@ -3427,12 +3431,15 @@ static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
        Py_ssize_t i, j = 0;
        PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
        if (msg->dn != NULL) {
-               PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
+               PyObject *obj = pyldb_Dn_FromDn(msg->dn);
+               PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", obj));
+               Py_CLEAR(obj);
                j++;
        }
        for (i = 0; i < msg->num_elements; i++, j++) {
                PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
                PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
+               Py_CLEAR(py_el);
                PyList_SetItem(l, j, value);
        }
        return l;
index 629ff0a4fd373a9e1215ba563e5da4a26f662886..d2a8e05a667c2804598131bd90e34bff0b42fb25 100644 (file)
@@ -1124,13 +1124,14 @@ static NTSTATUS list_helper(const char *mntpoint, struct file_info *finfo,
 {
        PyObject *result = (PyObject *)state;
        PyObject *file = NULL;
+       PyObject *size = NULL;
        int ret;
 
        /* suppress '.' and '..' in the results we return */
        if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
                return NT_STATUS_OK;
        }
-
+       size = PyLong_FromUnsignedLongLong(finfo->size);
        /*
         * Build a dictionary representing the file info.
         * Note: Windows does not always return short_name (so it may be None)
@@ -1139,10 +1140,12 @@ static NTSTATUS list_helper(const char *mntpoint, struct file_info *finfo,
                             "name", finfo->name,
                             "attrib", (int)finfo->mode,
                             "short_name", finfo->short_name,
-                            "size", PyLong_FromUnsignedLongLong(finfo->size),
+                            "size", size,
                             "mtime",
                             convert_timespec_to_time_t(finfo->mtime_ts));
 
+       Py_CLEAR(size);
+
        if (file == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
index a4441ddef5622086a801f162d38f655d2f798a82..16d22dfe4b8df2176dc40e382a438659adfc1337 100644 (file)
@@ -100,6 +100,7 @@ static PyObject *py_dsdb_dns_lookup(PyObject *self,
        struct ldb_context *samdb;
        PyObject *py_ldb, *ret, *pydn;
        PyObject *py_dns_partition = NULL;
+       PyObject *result = NULL;
        char *dns_name;
        TALLOC_CTX *frame;
        NTSTATUS status;
@@ -156,7 +157,10 @@ static PyObject *py_dsdb_dns_lookup(PyObject *self,
        ret = py_dnsp_DnssrvRpcRecord_get_list(records, num_records);
        pydn = pyldb_Dn_FromDn(dn);
        talloc_free(frame);
-       return Py_BuildValue("(OO)", pydn, ret);
+       result = Py_BuildValue("(OO)", pydn, ret);
+       Py_CLEAR(ret);
+       Py_CLEAR(pydn);
+       return result;
 }
 
 static PyObject *py_dsdb_dns_extract(PyObject *self, PyObject *args)