ITS#7705,#7800 fix back-mdb pagedResults search

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.
This commit is contained in:
Howard Chu 2014-05-15 20:46:20 -07:00
parent 141f168093
commit 437f21b16e
3 changed files with 27 additions and 8 deletions

View 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;

View File

@ -88,6 +88,7 @@ typedef struct IdScopes {
MDB_cursor *mc;
ID id;
ID2L scopes;
ID2L sctmp;
int numrdns;
int nscope;
int oscope;

View 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 ) {