The branch, master has been updated via c05b0a3 pyldb: Add tests for type errors via 379b919 pyldb: Report errors converting controls list to char** via 229935e pyldb: Better error reporting via d460bab pyldb: Type-check arguments parsed with PyArg_ParseTuple* via d599dcb pyldb: Fix reference leaks via 359e86a pyldb: Remove use of staticforward macro via f87e6df pyldb: Properly preallocate result control list via 92ff259 pyldb: Use the Py_TYPE macro via 39b08c7 pyldb: Correct reference counting when returning bools from 6b89848 pam: Fix CID 1034871 Resource leak
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit c05b0a35a2f911e0e16a87d6d883fa76feb362b7 Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:14 2015 +0100 pyldb: Add tests for type errors Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Wed Mar 4 01:49:02 CET 2015 on sn-devel-104 commit 379b919e4b5e0c309bd9ef65e84350760b788b03 Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:13 2015 +0100 pyldb: Report errors converting controls list to char** With this change, passing an unexpected type to the CRUD methods will result in an informative TypeError. Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 229935e03686ebdbd4f01cd2939e4399b68c33ec Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:12 2015 +0100 pyldb: Better error reporting Provide more useful error messages for some type errors Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d460bab949ef48ca4e77864d624da5834dabd057 Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:11 2015 +0100 pyldb: Type-check arguments parsed with PyArg_ParseTuple* PyObject* arguments need to be type-checked before they're cast to subtypes. Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d599dcb6bcac3b7b1600694be38937db0e8719b7 Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:10 2015 +0100 pyldb: Fix reference leaks The parse_ldif and MessageElement.__iter__ functions leaked references to intermediate lists whose iterators they return. The MessageElement repr used the undocumented macro PyObject_REPR, which leaks references. (It was used internally in CPython before fatal errors, and will be removed in Python 3.5.) Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 359e86af28719fd84e3b15cfb709536132dc2c14 Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:09 2015 +0100 pyldb: Remove use of staticforward macro Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f87e6df34ac05b352c6c74bf1fd1d678ee23217f Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:08 2015 +0100 pyldb: Properly preallocate result control list The list was always allocated with size 1, so if there is more than 1 result control, the additional items would not be added in the list, and would become leaked references. Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 92ff259f409cfeffc24ef9d7db8ab16217367bab Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:07 2015 +0100 pyldb: Use the Py_TYPE macro The "ob_type" member of Python objects is going away in Python 3 for compliance with C's strict aliasing rules. The Py_TYPE macro should be used instead. Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 39b08c7c1ee2173e47c8e9d381b89c4d74a5e0f5 Author: Petr Viktorin <pvikt...@redhat.com> Date: Tue Mar 3 22:29:06 2015 +0100 pyldb: Correct reference counting when returning bools Simply returning Py_True/PyFalse doesn't increment the bool object's reference count. Signed-off-by: Petr Viktorin <pvikt...@redhat.com> Reviewed-by: Jelmer Vernooij <jel...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/ldb/pyldb.c | 80 +++++++++++++++++++++++++++++++-------------- lib/ldb/tests/python/api.py | 42 ++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 25 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 5bcff72..f18e06e 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -48,7 +48,7 @@ static PyTypeObject PyLdb; static PyTypeObject PyLdbMessageElement; #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement) -staticforward PyTypeObject PyLdbTree; +static PyTypeObject PyLdbTree; static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx); static PyObject *PyLdbModule_FromModule(struct ldb_module *mod); static struct ldb_message_element *PyObject_AsMessageElement( @@ -88,7 +88,7 @@ static void py_ldb_control_dealloc(PyLdbControlObject *self) talloc_free(self->mem_ctx); } self->data = NULL; - self->ob_type->tp_free(self); + Py_TYPE(self)->tp_free(self); } static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self) @@ -121,9 +121,9 @@ static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject TALLOC_CTX *mem_ctx; struct ldb_context *ldb_ctx; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s", discard_const_p(char *, kwnames), - &py_ldb, &data)) + &PyLdb, &py_ldb, &data)) return NULL; mem_ctx = talloc_new(NULL); @@ -269,7 +269,11 @@ static PyObject *PyLdbResult_FromResult(struct ldb_result *result) ret->msgs = list; if (result->controls) { - controls = PyList_New(1); + i = 0; + while (result->controls[i]) { + i++; + } + controls = PyList_New(i); if (controls == NULL) { Py_DECREF(ret); PyErr_NoMemory(); @@ -457,7 +461,7 @@ static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s", &name)) return NULL; - return ldb_dn_check_special(self->dn, name)?Py_True:Py_False; + return PyBool_FromLong(ldb_dn_check_special(self->dn, name)); } static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2) @@ -507,7 +511,7 @@ static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args) if (!pyldb_Object_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other)) return NULL; - return ldb_dn_add_child(dn, other)?Py_True:Py_False; + return PyBool_FromLong(ldb_dn_add_child(dn, other)); } static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args) @@ -522,7 +526,7 @@ static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args) if (!pyldb_Object_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other)) return NULL; - return ldb_dn_add_base(dn, other)?Py_True:Py_False; + return PyBool_FromLong(ldb_dn_add_base(dn, other)); } static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args) @@ -534,7 +538,7 @@ static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject dn = pyldb_Dn_AsDn((PyObject *)self); - return ldb_dn_remove_base_components(dn, i)?Py_True:Py_False; + return PyBool_FromLong(ldb_dn_remove_base_components(dn, i)); } static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args) @@ -1105,6 +1109,10 @@ static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwar parsed_controls = NULL; } else { const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); talloc_free(controls); } @@ -1209,7 +1217,7 @@ static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx, msg_el = PyObject_AsMessageElement(msg->elements, value, mod_flags, key_str); if (msg_el == NULL) { - PyErr_SetString(PyExc_TypeError, "unable to import element"); + PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str); return NULL; } memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el)); @@ -1250,6 +1258,10 @@ static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs) parsed_controls = NULL; } else { const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); talloc_free(controls); } @@ -1339,6 +1351,10 @@ static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwar parsed_controls = NULL; } else { const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); talloc_free(controls); } @@ -1413,6 +1429,10 @@ static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwar parsed_controls = NULL; } else { const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); talloc_free(controls); } @@ -1542,7 +1562,7 @@ static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args) static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args) { - PyObject *list; + PyObject *list, *ret; struct ldb_ldif *ldif; const char *s; @@ -1569,7 +1589,9 @@ static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args) } } talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */ - return PyObject_GetIter(list); + ret = PyObject_GetIter(list); + Py_DECREF(list); + return ret; } static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args) @@ -1711,6 +1733,10 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar parsed_controls = NULL; } else { const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); + if (controls == NULL) { + talloc_free(mem_ctx); + return NULL; + } parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); talloc_free(controls); } @@ -1993,7 +2019,7 @@ static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx) static void py_ldb_dealloc(PyLdbObject *self) { talloc_free(self->mem_ctx); - self->ob_type->tp_free(self); + Py_TYPE(self)->tp_free(self); } static PyTypeObject PyLdb = { @@ -2017,7 +2043,7 @@ static void py_ldb_result_dealloc(PyLdbResultObject *self) Py_DECREF(self->msgs); Py_DECREF(self->referals); Py_DECREF(self->controls); - self->ob_type->tp_free(self); + Py_TYPE(self)->tp_free(self); } static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure) @@ -2135,9 +2161,9 @@ static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, P const char * const*attrs; /* type "int" rather than "enum" for "scope" is intentional */ - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO", discard_const_p(char *, kwnames), - &py_base, &scope, &py_tree, &py_attrs)) + &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs)) return NULL; mod = self->mod; @@ -2179,7 +2205,7 @@ static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args) int ret; struct ldb_module *mod; - if (!PyArg_ParseTuple(args, "O", &py_message)) + if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message)) return NULL; req = talloc_zero(NULL, struct ldb_request); @@ -2201,7 +2227,7 @@ static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) PyObject *py_message; struct ldb_module *mod; - if (!PyArg_ParseTuple(args, "O", &py_message)) + if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message)) return NULL; req = talloc_zero(NULL, struct ldb_request); @@ -2222,7 +2248,7 @@ static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) struct ldb_request *req; PyObject *py_dn; - if (!PyArg_ParseTuple(args, "O", &py_dn)) + if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn)) return NULL; req = talloc_zero(NULL, struct ldb_request); @@ -2242,7 +2268,7 @@ static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args) struct ldb_request *req; PyObject *py_dn1, *py_dn2; - if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2)) + if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2)) return NULL; req = talloc_zero(NULL, struct ldb_request); @@ -2446,7 +2472,9 @@ static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self) { PyObject *el = ldb_msg_element_to_set(NULL, pyldb_MessageElement_AsMessageElement(self)); - return PyObject_GetIter(el); + PyObject *ret = PyObject_GetIter(el); + Py_DECREF(el); + return ret; } static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx) @@ -2558,14 +2586,16 @@ static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self) char *element_str = NULL; Py_ssize_t i; struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self); - PyObject *ret; + PyObject *ret, *repr; for (i = 0; i < el->num_values; i++) { PyObject *o = py_ldb_msg_element_find(self, i); + repr = PyObject_Repr(o); if (element_str == NULL) - element_str = talloc_strdup(NULL, PyObject_REPR(o)); + element_str = talloc_strdup(NULL, PyString_AsString(repr)); else - element_str = talloc_asprintf_append(element_str, ",%s", PyObject_REPR(o)); + element_str = talloc_asprintf_append(element_str, ",%s", PyString_AsString(repr)); + Py_DECREF(repr); } if (element_str != NULL) { @@ -2958,7 +2988,7 @@ static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *cl { struct ldb_message *msg = pyldb_Message_AsMessage(self); if (!pyldb_Dn_Check(value)) { - PyErr_SetNone(PyExc_TypeError); + PyErr_SetString(PyExc_TypeError, "expected dn"); return -1; } diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py index 7f5c504..d101de8 100755 --- a/lib/ldb/tests/python/api.py +++ b/lib/ldb/tests/python/api.py @@ -776,6 +776,48 @@ class LdbResultTests(TestCase): self.assertTrue(found) +class BadTypeTests(TestCase): + def test_control(self): + l = ldb.Ldb() + self.assertRaises(TypeError, ldb.Control, '<bad type>', 'relax:1') + self.assertRaises(TypeError, ldb.Control, ldb, 1234) + + def test_modify(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + m = ldb.Message(dn) + self.assertRaises(TypeError, l.modify, '<bad type>') + self.assertRaises(TypeError, l.modify, m, '<bad type>') + + def test_add(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + m = ldb.Message(dn) + self.assertRaises(TypeError, l.add, '<bad type>') + self.assertRaises(TypeError, l.add, m, '<bad type>') + + def test_delete(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + self.assertRaises(TypeError, l.add, '<bad type>') + self.assertRaises(TypeError, l.add, dn, '<bad type>') + + def test_rename(self): + l = ldb.Ldb() + dn = ldb.Dn(l, 'a=b') + self.assertRaises(TypeError, l.add, '<bad type>', dn) + self.assertRaises(TypeError, l.add, dn, '<bad type>') + self.assertRaises(TypeError, l.add, dn, dn, '<bad type>') + + def test_search(self): + l = ldb.Ldb() + self.assertRaises(TypeError, l.search, base=1234) + self.assertRaises(TypeError, l.search, scope='<bad type>') + self.assertRaises(TypeError, l.search, expression=1234) + self.assertRaises(TypeError, l.search, attrs='<bad type>') + self.assertRaises(TypeError, l.search, controls='<bad type>') + + class VersionTests(TestCase): def test_version(self): -- Samba Shared Repository