]> git.sur5r.net Git - openldap/commitdiff
ITS#2795 fix double-free on failure, reset dn2id database
authorHoward Chu <hyc@openldap.org>
Wed, 3 Dec 2003 11:31:43 +0000 (11:31 +0000)
committerHoward Chu <hyc@openldap.org>
Wed, 3 Dec 2003 11:31:43 +0000 (11:31 +0000)
servers/slapd/back-ldbm/modrdn.c

index f7ed89fd682d7839bf861e3a13809b7fecca2563..ea5e71ee824a105779be98946c1d3ef70b72a23e 100644 (file)
@@ -43,15 +43,13 @@ ldbm_back_modrdn(
        struct ldbminfo *li = (struct ldbminfo *) op->o_bd->be_private;
        struct berval   p_dn, p_ndn;
        struct berval   new_dn = { 0, NULL}, new_ndn = { 0, NULL };
+       struct berval   old_ndn = { 0, NULL };
        Entry           *e, *p = NULL;
        Entry           *matched;
        /* LDAP v2 supporting correct attribute handling. */
        LDAPRDN         new_rdn = NULL;
        LDAPRDN         old_rdn = NULL;
        int             isroot = -1;
-#define CAN_ROLLBACK   -1
-#define MUST_DESTROY   1
-       int             rc = CAN_ROLLBACK;
        int             rc_id = 0;
        ID              id = NOID;
        const char      *text = NULL;
@@ -598,12 +596,11 @@ ldbm_back_modrdn(
        }
 
        (void) cache_delete_entry( &li->li_cache, e );
-       rc = MUST_DESTROY;
 
        /* XXX: there is no going back! */
 
        free( e->e_dn );
-       free( e->e_ndn );
+       old_ndn = e->e_nname;
        e->e_name = new_dn;
        e->e_nname = new_ndn;
        new_dn.bv_val = NULL;
@@ -633,7 +630,8 @@ ldbm_back_modrdn(
        
        default:
                /* here we may try to delete the newly added dn */
-               if ( dn2id_delete( op->o_bd, &e->e_nname, e->e_id ) != 0 ) {
+               if ( dn2id_delete( op->o_bd, &e->e_nname, e->e_id ) != 0 ||
+                       dn2id_add( op->o_bd, &old_ndn, e->e_id ) != 0 ) {
                        /* we already are in trouble ... */
                        ;
                }
@@ -653,12 +651,12 @@ ldbm_back_modrdn(
        rs->sr_err = LDAP_SUCCESS;
        rs->sr_text = NULL;
        send_ldap_result( op, rs );
-       rc = 0;
        cache_entry_commit( e );
 
 return_results:
        if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
        if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
+       if( old_ndn.bv_val != NULL ) free( old_ndn.bv_val );
 
        /* LDAP v2 supporting correct attribute handling. */
        if ( new_rdn != NULL ) {
@@ -695,13 +693,7 @@ return_results:
 
        /* free entry and writer lock */
        cache_return_entry_w( &li->li_cache, e );
-       if ( rc == MUST_DESTROY ) {
-               /* if rc == MUST_DESTROY the entry is uncached 
-                * and its private data is destroyed; 
-                * the entry must be freed */
-               entry_free( e );
-       }
        ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
        rs->sr_text = NULL;
-       return( rc );
+       return( rs->sr_err );
 }