pydsdb: Fix returning of ldb.MessageElement.
authorAndrew Bartlett <abartlet@samba.org>
Tue, 16 Feb 2016 02:15:44 +0000 (15:15 +1300)
committerKarolin Seeger <kseeger@samba.org>
Thu, 21 Apr 2016 07:09:25 +0000 (09:09 +0200)
This object is not based on pytalloc_Object and so this causes
a segfault (later a failure) when the struct definitions diverge.
We must also not reuse the incoming ldb_message_element as a talloc
context and overwrite the values, instead we should create a new
object and return that.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
(cherry picked from commit b96b1e88f760c92c7d9bb7e732f72d7e73a68907)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11789

source4/dsdb/pydsdb.c

index 8e7bff556ca3970f5eba15eb2ff500f0b9b39f8e..704fe10ff5f939bf5e805bb37fbd7cfa06ffdfdf 100644 (file)
@@ -557,6 +557,11 @@ static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
                                        "list of strings or ldb MessageElement object required");
                        return NULL;
                }
+               /*
+                * NOTE:
+                * el may not be a valid talloc context, it
+                * could be part of an array
+                */
                el = pyldb_MessageElement_AsMessageElement(el_list);
        } else {
                el = talloc_zero(tmp_ctx, struct ldb_message_element);
@@ -611,17 +616,20 @@ static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
  */
 static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
 {
-       PyObject *py_ldb, *el_list, *ret;
+       PyObject *py_ldb, *el_list, *py_ret;
        struct ldb_context *ldb;
        char *ldap_display_name;
        const struct dsdb_attribute *a;
        struct dsdb_schema *schema;
        struct dsdb_syntax_ctx syntax_ctx;
-       struct ldb_message_element *el;
+       struct ldb_message_element *el, *new_el;
        struct drsuapi_DsReplicaAttribute *attr;
+       PyLdbMessageElementObject *ret;
        TALLOC_CTX *tmp_ctx;
        WERROR werr;
        Py_ssize_t i;
+       PyTypeObject *py_type = NULL;
+       PyObject *module = NULL;
 
        if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
                return NULL;
@@ -656,6 +664,11 @@ static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
                                        "list of strings or ldb MessageElement object required");
                        return NULL;
                }
+               /*
+                * NOTE:
+                * el may not be a valid talloc context, it
+                * could be part of an array
+                */
                el = pyldb_MessageElement_AsMessageElement(el_list);
        } else {
                el = talloc_zero(tmp_ctx, struct ldb_message_element);
@@ -687,10 +700,17 @@ static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
                }
        }
 
+       new_el = talloc_zero(tmp_ctx, struct ldb_message_element);
+       if (new_el == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tmp_ctx);
+               return NULL;
+       }
+
        /* Normalise "objectClass" attribute if needed */
        if (ldb_attr_cmp(a->lDAPDisplayName, "objectClass") == 0) {
                int iret;
-               iret = dsdb_sort_objectClass_attr(ldb, schema, el, tmp_ctx, el);
+               iret = dsdb_sort_objectClass_attr(ldb, schema, el, new_el, new_el);
                if (iret != LDB_SUCCESS) {
                        PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
                        talloc_free(tmp_ctx);
@@ -713,14 +733,31 @@ static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
        PyErr_WERROR_NOT_OK_RAISE(werr);
 
        /* now convert back again */
-       werr = a->syntax->drsuapi_to_ldb(&syntax_ctx, a, attr, el, el);
+       werr = a->syntax->drsuapi_to_ldb(&syntax_ctx, a, attr, new_el, new_el);
        PyErr_WERROR_NOT_OK_RAISE(werr);
 
-       ret = py_return_ndr_struct("ldb", "MessageElement", el, el);
+       module = PyImport_ImportModule("ldb");
+       if (module == NULL) {
+               return NULL;
+       }
+
+       py_type = (PyTypeObject *)PyObject_GetAttrString(module, "MessageElement");
+       if (py_type == NULL) {
+               return NULL;
+       }
+       py_ret = py_type->tp_alloc(py_type, 0);
+       ret = (PyLdbMessageElementObject *)py_ret;
+
+       ret->mem_ctx = talloc_new(NULL);
+       if (talloc_reference(ret->mem_ctx, new_el) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+       ret->el = new_el;
 
        talloc_free(tmp_ctx);
 
-       return ret;
+       return py_ret;
 }