]> git.sur5r.net Git - openldap/commitdiff
ITS#7705,#7800 fix back-mdb pagedResults search
authorHoward Chu <hyc@openldap.org>
Fri, 16 May 2014 03:46:20 +0000 (20:46 -0700)
committerHoward Chu <hyc@openldap.org>
Fri, 16 May 2014 04:06:17 +0000 (21:06 -0700)
mdb_idscopes was remembering the IDs of every entry it checked;
it should only have been saving the IDs of entries that were
actually in the search scope. The extra entries filled the scopes
array, causing a loop searching for a parent entry that was
never inserted.

servers/slapd/back-mdb/dn2id.c
servers/slapd/back-mdb/idl.h
servers/slapd/back-mdb/search.c

index ceacb1796fe166bef342f42821d70fbfd7093249..b0e6905c7b439e1029b3e186dc8079707e4f3c0a 100644 (file)
@@ -703,7 +703,7 @@ mdb_idscopes(
        ID2 id2;
        char    *ptr;
        int             rc = 0;
-       unsigned int x;
+       unsigned int x, y;
        unsigned int nrlen, rlen;
        diskNode *d;
 
@@ -723,6 +723,7 @@ mdb_idscopes(
                return MDB_SUCCESS;
        }
 
+       isc->sctmp[0].mid = 0;
        while (id) {
                if ( !rc ) {
                        key.mv_data = &id;
@@ -742,21 +743,34 @@ mdb_idscopes(
                isc->numrdns++;
 
                if (!rc && id != isc->id) {
+                       /* remember our chain of parents */
                        id2.mid = id;
                        id2.mval = data;
-                       mdb_id2l_insert( isc->scopes, &id2 );
+                       mdb_id2l_insert( isc->sctmp, &id2 );
                }
                ptr = data.mv_data;
                ptr += data.mv_size - sizeof(ID);
                memcpy( &id, ptr, sizeof(ID) );
+               y = x;
                x = mdb_id2l_search( isc->scopes, id );
                if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id ) {
                        if ( !isc->scopes[x].mval.mv_data ) {
+                               /* This node is in scope, add parent chain to scope */
+                               int i = isc->sctmp[0].mid;
+                               for ( i = 1; i <= isc->sctmp[0].mid; i++ )
+                                       mdb_id2l_insert( isc->scopes, &isc->sctmp[i] );
+                               /* check id again since inserts may have changed its position */
+                               if ( isc->scopes[x].mid != id )
+                                       x = mdb_id2l_search( isc->scopes, id );
                                isc->nscope = x;
                                return MDB_SUCCESS;
                        }
                        data = isc->scopes[x].mval;
                        rc = 1;
+               } else {
+                       /* If we didn't advance, some parent is missing */
+                       if ( x == y )
+                               return MDB_NOTFOUND;
                }
                if ( op->ors_scope == LDAP_SCOPE_ONELEVEL )
                        break;
index d614b5bff99b99638eaf9ae4e9b61c5dbfd10036..ea862f2148b43e64d4e1765bd2aa80fe17d43235 100644 (file)
@@ -88,6 +88,7 @@ typedef struct IdScopes {
        MDB_cursor *mc;
        ID id;
        ID2L scopes;
+       ID2L sctmp;
        int numrdns;
        int nscope;
        int oscope;
index fd4876252996d14f493a78ce9e8a455b524a270a..9872c52205d7292bf7ea6974c606742a8d8794e2 100644 (file)
@@ -34,7 +34,8 @@ static int search_candidates(
        MDB_txn *txn,
        MDB_cursor *mci,
        ID      *ids,
-       ID2L    scopes );
+       ID2L    scopes,
+       ID *stack );
 
 static int parse_paged_cookie( Operation *op, SlapReply *rs );
 
@@ -313,6 +314,8 @@ static void scope_chunk_ret( Operation *op, ID2 *scopes )
                        (void *)scopes, scope_chunk_free, NULL, NULL );
 }
 
+static void *search_stack( Operation *op );
+
 int
 mdb_search( Operation *op, SlapReply *rs )
 {
@@ -322,6 +325,7 @@ mdb_search( Operation *op, SlapReply *rs )
        ID              candidates[MDB_IDL_UM_SIZE];
        ID              iscopes[MDB_IDL_DB_SIZE];
        ID2             *scopes;
+       void    *stack;
        Entry           *e = NULL, *base = NULL;
        Entry           *matched = NULL;
        AttributeName   *attrs;
@@ -365,10 +369,12 @@ mdb_search( Operation *op, SlapReply *rs )
        }
 
        scopes = scope_chunk_get( op );
+       stack = search_stack( op );
        isc.mt = ltid;
        isc.mc = mcd;
        isc.scopes = scopes;
        isc.oscope = op->ors_scope;
+       isc.sctmp = stack;
 
        if ( op->ors_deref & LDAP_DEREF_FINDING ) {
                MDB_IDL_ZERO(candidates);
@@ -562,7 +568,7 @@ dn2entry_retry:
                scopes[1].mid = base->e_id;
                scopes[1].mval.mv_data = NULL;
                rs->sr_err = search_candidates( op, rs, base,
-                       ltid, mci, candidates, scopes );
+                       ltid, mci, candidates, scopes, stack );
                ncand = MDB_IDL_N( candidates );
                if ( !base->e_id || ncand == NOID ) {
                        /* grab entry count from id2entry stat
@@ -1161,12 +1167,12 @@ static int search_candidates(
        MDB_txn *txn,
        MDB_cursor *mci,
        ID      *ids,
-       ID2L    scopes )
+       ID2L    scopes,
+       ID *stack )
 {
        struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
        int rc, depth = 1;
        Filter          *f, rf, xf, nf, sf;
-       ID              *stack;
        AttributeAssertion aa_ref = ATTRIBUTEASSERTION_INIT;
        AttributeAssertion aa_subentry = ATTRIBUTEASSERTION_INIT;
 
@@ -1221,8 +1227,6 @@ static int search_candidates(
        /* Allocate IDL stack, plus 1 more for former tmp */
        if ( depth+1 > mdb->mi_search_stack_depth ) {
                stack = ch_malloc( (depth + 1) * MDB_IDL_UM_SIZE * sizeof( ID ) );
-       } else {
-               stack = search_stack( op );
        }
 
        if( op->ors_deref & LDAP_DEREF_SEARCHING ) {