Skip to content

Commit a72aaac

Browse files
tiranencukou
authored andcommitted
Fix multiple ref leaks when raising TypeError
Multiple functions had a reference leak while raising a TypeError with Py_BuildValue(). The CAPI function Py_BuildValue() returns a new reference. PyErr_SetObject() does NOT consume the reference. Instead it increments the reference count of the object again. A new function LDAPerror_TypeError() handles raising TypeError with custom message and object. https://github.com/python-ldap/python-ldap/pull/31/files Closes: #24 Signed-off-by: Christian Heimes <cheimes@redhat.com>
1 parent 4aa0d36 commit a72aaac

File tree

4 files changed

+36
-32
lines changed

4 files changed

+36
-32
lines changed

Modules/LDAPObject.c

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,7 @@ Tuple_to_LDAPMod( PyObject* tup, int no_op )
113113
Py_ssize_t i, len, nstrs;
114114

115115
if (!PyTuple_Check(tup)) {
116-
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
117-
"expected a tuple", tup));
118-
return NULL;
116+
return LDAPerror_TypeError("expected a tuple", tup);
119117
}
120118

121119
if (no_op) {
@@ -167,9 +165,7 @@ Tuple_to_LDAPMod( PyObject* tup, int no_op )
167165
if (item == NULL)
168166
goto error;
169167
if (!PyBytes_Check(item)) {
170-
PyErr_SetObject( PyExc_TypeError, Py_BuildValue( "sO",
171-
"expected a byte string in the list", item));
172-
Py_DECREF(item);
168+
LDAPerror_TypeError("expected a byte string in the list", item);
173169
goto error;
174170
}
175171
lm->mod_bvalues[i]->bv_len = PyBytes_Size(item);
@@ -214,17 +210,13 @@ List_to_LDAPMods( PyObject *list, int no_op ) {
214210
PyObject *item;
215211

216212
if (!PySequence_Check(list)) {
217-
PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
218-
"expected list of tuples", list ));
219-
return NULL;
213+
return LDAPerror_TypeError("expected list of tuples", list);
220214
}
221215

222216
len = PySequence_Length(list);
223217

224218
if (len < 0) {
225-
PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
226-
"expected list of tuples", list ));
227-
return NULL;
219+
return LDAPerror_TypeError("expected list of tuples", list);
228220
}
229221

230222
lms = PyMem_NEW(LDAPMod *, len + 1);
@@ -274,8 +266,8 @@ attrs_from_List( PyObject *attrlist, char***attrsp, PyObject** seq) {
274266
} else if (PyUnicode_Check(attrlist)) {
275267
#endif
276268
/* caught by John Benninghoff <johnb@netscape.com> */
277-
PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
278-
"expected *list* of strings, not a string", attrlist ));
269+
LDAPerror_TypeError(
270+
"expected *list* of strings, not a string", attrlist);
279271
goto error;
280272
} else {
281273
*seq = PySequence_Fast(attrlist, "expected list of strings or None");
@@ -296,16 +288,15 @@ attrs_from_List( PyObject *attrlist, char***attrsp, PyObject** seq) {
296288
#if PY_MAJOR_VERSION == 2
297289
/* Encoded by Python to UTF-8 */
298290
if (!PyBytes_Check(item)) {
299-
#else
300-
if (!PyUnicode_Check(item)) {
301-
#endif
302-
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
303-
"expected string in list", item));
291+
LDAPerror_TypeError("expected bytes in list", item);
304292
goto error;
305293
}
306-
#if PY_MAJOR_VERSION == 2
307294
attrs[i] = PyBytes_AsString(item);
308295
#else
296+
if (!PyUnicode_Check(item)) {
297+
LDAPerror_TypeError("expected string in list", item);
298+
goto error;
299+
}
309300
attrs[i] = PyUnicode_AsUTF8(item);
310301
#endif
311302
}

Modules/errors.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@ static PyObject* errobjects[ LDAP_ERROR_MAX-LDAP_ERROR_MIN+1 ];
3636
PyObject*
3737
LDAPerr(int errnum)
3838
{
39-
if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX)
39+
if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) {
4040
PyErr_SetNone(errobjects[errnum+LDAP_ERROR_OFFSET]);
41-
else
42-
PyErr_SetObject(LDAPexception_class,
43-
Py_BuildValue("{s:i}", "errnum", errnum));
41+
} else {
42+
PyObject *args = Py_BuildValue("{s:i}", "errnum", errnum);
43+
if (args == NULL)
44+
return NULL;
45+
PyErr_SetObject(LDAPexception_class, args);
46+
Py_DECREF(args);
47+
}
4448
return NULL;
4549
}
4650

@@ -123,6 +127,18 @@ LDAPerror( LDAP *l, char *msg )
123127
}
124128
}
125129

130+
/* Raise TypeError with custom message and object */
131+
PyObject*
132+
LDAPerror_TypeError(const char *msg, PyObject *obj) {
133+
PyObject *args = Py_BuildValue("sO", msg, obj);
134+
if (args == NULL) {
135+
return NULL;
136+
}
137+
PyErr_SetObject(PyExc_TypeError, args);
138+
Py_DECREF(args);
139+
return NULL;
140+
}
141+
126142

127143
/* initialisation */
128144

Modules/errors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
extern PyObject* LDAPexception_class;
1111
extern PyObject* LDAPerror( LDAP*, char*msg );
12+
extern PyObject* LDAPerror_TypeError(const char *, PyObject *);
1213
extern void LDAPinit_errors( PyObject* );
1314
PyObject* LDAPerr(int errnum);
1415

Modules/ldapcontrol.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@ Tuple_to_LDAPControl( PyObject* tup )
7272
Py_ssize_t len;
7373

7474
if (!PyTuple_Check(tup)) {
75-
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
76-
"expected a tuple", tup));
77-
return NULL;
75+
return LDAPerror_TypeError("expected a tuple", tup);
7876
}
7977

8078
if (!PyArg_ParseTuple( tup, "sbO", &oid, &iscritical, &bytes ))
@@ -107,8 +105,7 @@ Tuple_to_LDAPControl( PyObject* tup )
107105
berbytes.bv_val = PyBytes_AsString(bytes);
108106
}
109107
else {
110-
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
111-
"expected bytes", bytes));
108+
LDAPerror_TypeError("expected bytes", bytes);
112109
LDAPControl_DEL(lc);
113110
return NULL;
114111
}
@@ -130,9 +127,8 @@ LDAPControls_from_object(PyObject* list, LDAPControl ***controls_ret)
130127
PyObject* item;
131128

132129
if (!PySequence_Check(list)) {
133-
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
134-
"expected a list", list));
135-
return 0;
130+
LDAPerror_TypeError("expected a list", list);
131+
return 0;
136132
}
137133

138134
len = PySequence_Length(list);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy