[Date Prev][Date Next] [Chronological] [Thread] [Top]

Release 1.2 ldbmcat problem with Berkeley DB (ITS#85)



Full_Name: Sumit A. Vakil
Version: 1.2
OS: FreeBSD
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (205.138.236.250)


I have OpenLDAP version 1.2 compiled on a FreeBSD 2.2.x system.  I'm using the
Berkeley DB 2.3.16 database.  ldbmcat does not work.  Running ldbmcat does not
produce any ldif output.  It also complains about chunks of memory being freed
again.

The problem is easy to reproduce.  Simply run ldbmcat (with or without the -n
option) on an existing db.

The details of the problem and a suggested fix are as follows:

The problem is that ldbm_firstkey() sets the key flags to DB_DBT_MALLOC whereas
the DB functions called by ldbm_fetch() expect the key flags to be zero.  I
fixed the problem by setting the key flags to zero before calling ldbm_fetch()
and then setting them back to DB_DBT_MALLOC.  Note that the key flags should be
set back to DB_DBT_MALLOC before calling ldbm_nextkey().

Another problem I noticed was that some chunks of memory were being free twice. 
The problem there is that ldbmcat tries to free key.data.  This memory is
already freed by ldbm_nextkey().  Removing the 
               if ( last.dptr != NULL )
                        ldbm_datum_free( dbp, last );
lines fixes the problem.

Updated main() in ldbmcat.c:

int
main( int argc, char **argv )
{
        Datum                key, last, data;
        LDBM                dbp;
        int                rc, type;
        long                id;
        char                *file, *s;
        int                printid = 1;

#ifdef HAVE_BERKELEY_DB2
        DBC        *cursorp;
#endif

        ldbm_datum_init( key );
        ldbm_datum_init( last );
        ldbm_datum_init( data );

        if ( argc < 2 || argc > 3 || ( argc == 3 && strcmp( argv[1], "-n" )
            != 0 )) {
                usage( argv[0] );
        }
        if ( argc == 3 && strcmp( argv[1], "-n" ) == 0 ) {
                printid = 0;
                file = argv[2];
        } else {
                file = argv[1];
        }

        if ( (dbp = ldbm_open( file, LDBM_READER, 0, 0 )) == NULL ) {
                perror( file );
                exit ( 1 );
        }

        last.dptr = NULL;

#ifdef HAVE_BERKELEY_DB2
        for ( key = ldbm_firstkey( dbp, &cursorp ); key.dptr != NULL;
            key = ldbm_nextkey( dbp, last, cursorp ) )
#else
        for ( key = ldbm_firstkey( dbp ); key.dptr != NULL;
            key = ldbm_nextkey( dbp, last ) )
#endif
        {
/* Begin Internet Devices mods. */
#ifdef HAVE_BERKELEY_DB2
                key.flags = 0;
                data = ldbm_fetch( dbp, key );
                key.flags = DB_DBT_MALLOC;
#else
                if ( last.dptr != NULL )
                        ldbm_datum_free( dbp, last );
                data = ldbm_fetch( dbp, key );
#endif HAVE_BERKELEY_DB2
/* End Internet Devices mods. */

                if (( s = data.dptr ) != NULL ) {

                    if ( !printid && isdigit( *s )) {

                        if (( s = strchr( s, '\n' )) != NULL ) {
                                ++s;
                        }
                    }
                    if ( s != NULL ) {
                        puts( s );
                    }

                    if ( data.dptr != NULL ) {
                        ldbm_datum_free( dbp, data );
                    }

                }

                last = key;
        }

/* Begin Internet Devices mods. */
#ifndef HAVE_BERKELEY_DB2
        if ( last.dptr != NULL )
                ldbm_datum_free( dbp, last );
#endif HAVE_BERKELEY_DB2
/* End Internet Devices mods. */

        ldbm_close( dbp );

        exit( 0 );
}