X Tutup
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)
X Tutup