More memory freeing patches to message.c
Michael Ströder
michael at stroeder.com
Thu Jul 12 11:38:49 CEST 2001
HI!
Following some more advice by Stig Venaas (see message below) I've
ifdef'ed some memory freeing calls provided by Steffen in message.c
to keep the source compatible to OpenLDAP 1.2.x libs. I've attached
my recent message.c.
Backwards compability is not assumed to be crucial in the long run
but seems nice if we can achieve it with fairly low efforts.
Ciao, Michael.
-------- Original Message --------
Subject: Re: python-ldap and OpenLDAP 2
Date: Thu, 12 Jul 2001 10:47:35 +0200
From: Stig Venaas <Stig.Venaas at uninett.no>
To: Michael Ströder <michael at stroeder.com>
References: <3B4382DD.C9B6A780 at stroeder.com>
<20010711184821.A6433 at sverresborg.uninett.no>
<3B4C94B9.5885D132 at stroeder.com>
<20010712090618.A7043 at sverresborg.uninett.no>
<3B4D525B.47107DC7 at stroeder.com>
On Thu, Jul 12, 2001 at 09:31:39AM +0200, Michael Ströder wrote:
> Stig Venaas wrote:
> >
> > These memory leaks was also reported and discussed
> > in the OpenLDAP ITS system a few days ago. Someone reported memory
> > leaks and Kurt and I responded. See
> > http://www.OpenLDAP.org/lists/openldap-bugs/200107/msg00018.html
> > for my respons.
>
> According to this and Steffen's message the ldap_memfree(attr) and
> ber_free(ber, 0) should be ifdef'ed. What about the free(dn) call?
>
> Well, we have no problems dropping support for linking against
> OpenLDAP 1.x completely if we will have a really stable version and
> it's clear that we can achieve all goals on this track.
PHP supports OpenLDAP 1.x and others that use the RFC1823 API, as
well as Netscape SDK and OpenLDAP 2.x and others that use the new
API. The same should be possible for Python.
I think I've found a bug in PHP when using old API and
ldap_get_dn().
It's not freed! I've never tested much with old API. The PHP code
looks
like this:
#if ( LDAP_API_VERSION > 2000 ) || HAVE_NSLDAP || WINDOWS
ldap_memfree(dn);
#endif
For Python you could use:
#if ( LDAP_API_VERSION > 2000 )
ldap_memfree(dn);
#else
free(dn);
#endif
ldap_memfree() is currently the same as free() but it should be done
this way anyway. Regarding the other leaks, you can use code like:
#if ( LDAP_API_VERSION > 2000 )
ldap_memfree(attribute);
#endif
and
#if ( LDAP_API_VERSION > 2000 )
if (ber != NULL)
ber_free(ber, 0);
#endif
This way it should work with both old and new APIs.
> I have changed the calls to free() to ldap_memfree(), which means
> the
> code will compile only against OpenLDAP 2.0.x, since 1.2 does not
> define ldap_memfree().
Hence the trick above.
Stig
-------------- next part --------------
/* David Leonard <david.leonard at csee.uq.edu.au>, 1999. Public domain. */
/*
* LDAPMessageObject - wrapper around an LDAPMessage*
* $Id: message.c,v 1.6 2000/08/18 00:21:46 leonard Exp $
*/
#include "common.h"
#include "message.h"
#include "errors.h"
#include "CIDict.h"
PyObject*
LDAPmessage_to_python( LDAP*ld, LDAPMessage*m )
{
/* we convert an LDAP message into a python structure.
* It is always a list of dictionaries.
* We always free m.
*/
PyObject* result;
LDAPMessage* entry;
result = PyList_New(0);
if (result == NULL) {
ldap_msgfree( m );
return NULL;
}
for(entry = ldap_first_entry(ld,m);
entry != NULL;
entry = ldap_next_entry(ld,entry))
{
char *dn;
char *attr;
BerElement *ber = NULL;
PyObject* entrytuple;
PyObject* attrdict;
dn = ldap_get_dn( ld, entry );
if (dn == NULL) {
Py_DECREF(result);
ldap_msgfree( m );
return LDAPerror( ld, "ldap_get_dn" );
}
#ifdef USE_CIDICT
attrdict = CIDict_New();
#else /* use standard python dictionary */
attrdict = PyDict_New();
#endif /* !CIDICT */
if (attrdict == NULL) {
Py_DECREF(result);
ldap_msgfree( m );
#if LDAP_API_VERSION >= 2000
ldap_memfree(dn);
#else
free(dn);
#endif
return NULL;
}
/* Fill attrdict with lists */
for( attr = ldap_first_attribute( ld, entry, &ber );
attr != NULL;
attr = ldap_next_attribute( ld, entry, ber )
) {
PyObject* valuelist;
struct berval ** bvals =
ldap_get_values_len( ld, entry, attr );
/* Find which list to append to */
if ( PyMapping_HasKeyString( attrdict, attr ) ) {
valuelist = PyMapping_GetItemString( attrdict, attr );
} else {
valuelist = PyList_New(0);
if (valuelist != NULL && PyMapping_SetItemString(attrdict,
attr, valuelist) == -1) {
Py_DECREF(valuelist);
valuelist = NULL; /* catch error later */
}
}
if (valuelist == NULL) {
Py_DECREF(attrdict);
Py_DECREF(result);
#if ( LDAP_API_VERSION > 2000 )
if (ber != NULL)
ber_free(ber, 0);
#endif
ldap_msgfree( m );
#if LDAP_API_VERSION >= 2000
ldap_memfree(attr);
ldap_memfree(dn);
#else
free(dn);
#endif
return NULL;
}
if (bvals != NULL) {
int i;
for (i=0; bvals[i]; i++) {
PyObject *valuestr;
valuestr = PyString_FromStringAndSize(
bvals[i]->bv_val, bvals[i]->bv_len
);
if (PyList_Append( valuelist, valuestr ) == -1) {
Py_DECREF(attrdict);
Py_DECREF(result);
Py_DECREF(valuestr);
Py_DECREF(valuelist);
ldap_msgfree( m );
#if LDAP_API_VERSION >= 2000
ldap_memfree(attr);
ldap_memfree(dn);
#else
free(dn);
#endif
return NULL;
}
Py_DECREF(valuestr);
}
ldap_value_free_len(bvals);
}
Py_DECREF( valuelist );
#if LDAP_API_VERSION >= 2000
ldap_memfree(attr);
#endif
}
entrytuple = Py_BuildValue("(sO)", dn, attrdict);
#if LDAP_API_VERSION >= 2000
ldap_memfree(dn);
#else
free(dn);
#endif
Py_DECREF(attrdict);
PyList_Append(result, entrytuple);
Py_DECREF(entrytuple);
#if ( LDAP_API_VERSION > 2000 )
if (ber != NULL)
ber_free(ber, 0);
#endif
}
#if LDAP_API_VERSION >= 2000
for(entry = ldap_first_reference(ld,m);
entry != NULL;
entry = ldap_next_reference(ld,entry))
{
char **refs = NULL;
PyObject* entrytuple;
PyObject* reflist = PyList_New(0);
if (reflist == NULL) {
Py_DECREF(result);
ldap_msgfree( m );
return NULL;
}
if (ldap_parse_reference(ld, entry, &refs, NULL, 0) != LDAP_SUCCESS) {
Py_DECREF(result);
ldap_msgfree( m );
return LDAPerror( ld, "ldap_parse_reference" );
}
if (refs) {
int i;
for (i=0; refs[i] != NULL; i++) {
PyObject *refstr = PyString_FromString(refs[i]);
PyList_Append(reflist, refstr);
Py_DECREF(refstr);
}
ber_memvfree( (void **) refs );
}
entrytuple = Py_BuildValue("(sO)", NULL, reflist);
Py_DECREF(reflist);
PyList_Append(result, entrytuple);
Py_DECREF(entrytuple);
}
#endif
ldap_msgfree( m );
return result;
}
More information about the python-ldap
mailing list