Skip to content

Commit baa091f

Browse files
tiranencukou
authored andcommitted
Change memory handling in attrs_from_List()
attrs_from_List() no longer uses internal buffers of bytes/str PyObject* to maintain memory. Instead it creates its own copies, which are then passed to ldap_search_ext() and then cleaned up. The modification is required for Python 3.7. PyUnicode_AsUTF8() returns const char* but ldap_search_ext() does not use const. python-ldap#106 Closes: python-ldap#105 Signed-off-by: Christian Heimes <cheimes@redhat.com>
1 parent 4d3cd7d commit baa091f

File tree

2 files changed

+51
-24
lines changed

2 files changed

+51
-24
lines changed

.travis.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ matrix:
3434
env:
3535
- TOXENV=py36
3636
- WITH_GCOV=1
37+
- python: 3.7-dev
38+
env:
39+
- TOXENV=py37
40+
- WITH_GCOV=1
3741
- python: 2.7
3842
env:
3943
- TOXENV=py2-nosasltls
@@ -44,6 +48,10 @@ matrix:
4448
- WITH_GCOV=1
4549
- python: 3.6
4650
env: TOXENV=doc
51+
allow_failures:
52+
- env:
53+
- TOXENV=py37
54+
- WITH_GCOV=1
4755

4856
env:
4957
global:

Modules/LDAPObject.c

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <sasl/sasl.h>
1717
#endif
1818

19-
static void free_attrs(char***, PyObject*);
19+
static void free_attrs(char***);
2020

2121
/* constructor */
2222

@@ -248,13 +248,10 @@ List_to_LDAPMods( PyObject *list, int no_op ) {
248248
*/
249249

250250
int
251-
attrs_from_List( PyObject *attrlist, char***attrsp, PyObject** seq) {
251+
attrs_from_List( PyObject *attrlist, char***attrsp) {
252252

253253
char **attrs = NULL;
254-
Py_ssize_t i, len;
255-
PyObject *item;
256-
257-
*seq = NULL;
254+
PyObject *seq = NULL;
258255

259256
if (attrlist == Py_None) {
260257
/* None means a NULL attrlist */
@@ -268,8 +265,16 @@ attrs_from_List( PyObject *attrlist, char***attrsp, PyObject** seq) {
268265
"expected *list* of strings, not a string", attrlist);
269266
goto error;
270267
} else {
271-
*seq = PySequence_Fast(attrlist, "expected list of strings or None");
272-
if (*seq == NULL)
268+
PyObject *item = NULL;
269+
Py_ssize_t i, len, strlen;
270+
#if PY_MAJOR_VERSION >= 3
271+
const char *str;
272+
#else
273+
char *str;
274+
#endif
275+
276+
seq = PySequence_Fast(attrlist, "expected list of strings or None");
277+
if (seq == NULL)
273278
goto error;
274279

275280
len = PySequence_Length(attrlist);
@@ -280,25 +285,36 @@ attrs_from_List( PyObject *attrlist, char***attrsp, PyObject** seq) {
280285

281286
for (i = 0; i < len; i++) {
282287
attrs[i] = NULL;
283-
item = PySequence_Fast_GET_ITEM(*seq, i);
288+
item = PySequence_Fast_GET_ITEM(seq, i);
284289
if (item == NULL)
285290
goto error;
286291
#if PY_MAJOR_VERSION == 2
287-
/* Encoded by Python to UTF-8 */
292+
/* Encoded in Python to UTF-8 */
288293
if (!PyBytes_Check(item)) {
289294
LDAPerror_TypeError("expected bytes in list", item);
290295
goto error;
291296
}
292-
attrs[i] = PyBytes_AsString(item);
297+
if (PyBytes_AsStringAndSize(item, &str, &strlen) == -1) {
298+
goto error;
299+
}
293300
#else
294301
if (!PyUnicode_Check(item)) {
295302
LDAPerror_TypeError("expected string in list", item);
296303
goto error;
297304
}
298-
attrs[i] = PyUnicode_AsUTF8(item);
305+
str = PyUnicode_AsUTF8AndSize(item, &strlen);
299306
#endif
307+
/* Make a copy. PyBytes_AsString* / PyUnicode_AsUTF8* return
308+
* internal values that must be treated like const char. Python
309+
* 3.7 actually returns a const char.
310+
*/
311+
attrs[i] = (char *)PyMem_NEW(char *, strlen + 1);
312+
if (attrs[i] == NULL)
313+
goto nomem;
314+
memcpy(attrs[i], str, strlen + 1);
300315
}
301316
attrs[len] = NULL;
317+
Py_DECREF(seq);
302318
}
303319

304320
*attrsp = attrs;
@@ -307,22 +323,26 @@ attrs_from_List( PyObject *attrlist, char***attrsp, PyObject** seq) {
307323
nomem:
308324
PyErr_NoMemory();
309325
error:
310-
free_attrs(&attrs, *seq);
326+
Py_XDECREF(seq);
327+
free_attrs(&attrs);
311328
return 0;
312329
}
313330

314331
/* free memory allocated from above routine */
315332

316333
static void
317-
free_attrs( char*** attrsp, PyObject* seq ) {
334+
free_attrs( char*** attrsp) {
318335
char **attrs = *attrsp;
336+
char **p;
319337

320-
if (attrs != NULL) {
321-
PyMem_DEL(attrs);
322-
*attrsp = NULL;
323-
}
338+
if (attrs == NULL)
339+
return;
324340

325-
Py_XDECREF(seq);
341+
*attrsp = NULL;
342+
for (p = attrs; *p != NULL; p++) {
343+
PyMem_DEL(*p);
344+
}
345+
PyMem_DEL(attrs);
326346
}
327347

328348
/*------------------------------------------------------------
@@ -1130,7 +1150,6 @@ l_ldap_search_ext( LDAPObject* self, PyObject* args )
11301150

11311151
PyObject *serverctrls = Py_None;
11321152
PyObject *clientctrls = Py_None;
1133-
PyObject *attrs_seq = NULL;
11341153
LDAPControl** server_ldcs = NULL;
11351154
LDAPControl** client_ldcs = NULL;
11361155

@@ -1148,7 +1167,7 @@ l_ldap_search_ext( LDAPObject* self, PyObject* args )
11481167
&serverctrls, &clientctrls, &timeout, &sizelimit )) return NULL;
11491168
if (not_valid(self)) return NULL;
11501169

1151-
if (!attrs_from_List( attrlist, &attrs, &attrs_seq ))
1170+
if (!attrs_from_List( attrlist, &attrs ))
11521171
return NULL;
11531172

11541173
if (timeout >= 0) {
@@ -1160,14 +1179,14 @@ l_ldap_search_ext( LDAPObject* self, PyObject* args )
11601179

11611180
if (!PyNone_Check(serverctrls)) {
11621181
if (!LDAPControls_from_object(serverctrls, &server_ldcs)) {
1163-
free_attrs( &attrs, attrs_seq);
1182+
free_attrs( &attrs );
11641183
return NULL;
11651184
}
11661185
}
11671186

11681187
if (!PyNone_Check(clientctrls)) {
11691188
if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
1170-
free_attrs( &attrs, attrs_seq);
1189+
free_attrs( &attrs );
11711190
LDAPControl_List_DEL( server_ldcs );
11721191
return NULL;
11731192
}
@@ -1178,7 +1197,7 @@ l_ldap_search_ext( LDAPObject* self, PyObject* args )
11781197
server_ldcs, client_ldcs, tvp, sizelimit, &msgid );
11791198
LDAP_END_ALLOW_THREADS( self );
11801199

1181-
free_attrs( &attrs, attrs_seq);
1200+
free_attrs( &attrs );
11821201
LDAPControl_List_DEL( server_ldcs );
11831202
LDAPControl_List_DEL( client_ldcs );
11841203

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