File 0013-ITS-8203-more-fixes-for-8036-7904.patch of Package openldap2.5013

From 3033f89eefceb3471ba032ff60aa7cd3980e975a Mon Sep 17 00:00:00 2001
From: Howard Chu <hyc@openldap.org>
Date: Fri, 24 Jul 2015 18:34:11 +0100
Subject: [PATCH] ITS#8203 more fixes for #8036/#7904.


diff --git a/servers/slapd/back-mdb/dn2id.c b/servers/slapd/back-mdb/dn2id.c
index d1845f7..43b82ce 100644
--- a/servers/slapd/back-mdb/dn2id.c
+++ b/servers/slapd/back-mdb/dn2id.c
@@ -922,3 +922,45 @@ mdb_dn2id_walk(
 	}
 	return rc;
 }
+
+/* restore the nrdn/rdn pointers after a txn reset */
+void mdb_dn2id_wrestore (
+	Operation *op,
+	IdScopes *isc
+)
+{
+	MDB_val key, data;
+	diskNode *d;
+	int rc, n, nrlen;
+	char *ptr;
+
+	/* We only need to restore up to the n-1th element,
+	 * the nth element will be replaced anyway
+	 */
+	key.mv_size = sizeof(ID);
+	for ( n=0; n<isc->numrdns-1; n++ ) {
+		key.mv_data = &isc->scopes[n+1].mid;
+		rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+		if ( rc )
+			continue;
+		/* we can't use this data directly since its nrlen
+		 * is missing the high bit setting, so copy it and
+		 * set it properly. we just copy enough to satisfy
+		 * mdb_dup_compare.
+		 */
+		d = data.mv_data;
+		nrlen = ((d->nrdnlen[0] & 0x7f) << 8) | d->nrdnlen[1];
+		ptr = op->o_tmpalloc( nrlen+2, op->o_tmpmemctx );
+		memcpy( ptr, data.mv_data, nrlen+2 );
+		key.mv_data = &isc->scopes[n].mid;
+		data.mv_data = ptr;
+		data.mv_size = 1;
+		*ptr |= 0x80;
+		mdb_cursor_get( isc->mc, &key, &data, MDB_GET_BOTH );
+
+		/* now we're back to where we wanted to be */
+		d = data.mv_data;
+		isc->nrdns[n].bv_val = d->nrdn;
+		isc->rdns[n].bv_val = d->nrdn+isc->nrdns[n].bv_len+1;
+	}
+}
diff --git a/servers/slapd/back-mdb/proto-mdb.h b/servers/slapd/back-mdb/proto-mdb.h
index b2873ec..abafa85 100644
--- a/servers/slapd/back-mdb/proto-mdb.h
+++ b/servers/slapd/back-mdb/proto-mdb.h
@@ -146,6 +146,10 @@ int mdb_dn2id_walk(
 	Operation *op,
 	struct IdScopes *isc );
 
+void mdb_dn2id_wrestore(
+	Operation *op,
+	struct IdScopes *isc );
+
 MDB_cmp_func mdb_dup_compare;
 
 /*
diff --git a/servers/slapd/back-mdb/search.c b/servers/slapd/back-mdb/search.c
index 1a99f97..14a2c6b 100644
--- a/servers/slapd/back-mdb/search.c
+++ b/servers/slapd/back-mdb/search.c
@@ -358,30 +358,22 @@ mdb_writewait( Operation *op, slap_callback *sc )
 }
 
 static int
-mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd, ID2 *scopes )
+mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd, IdScopes *isc )
 {
+	MDB_val key;
 	int rc = 0;
 	ww->flag = 0;
 	mdb_txn_renew( ww->txn );
 	mdb_cursor_renew( ww->txn, mci );
 	mdb_cursor_renew( ww->txn, mcd );
 
-	if ( scopes[0].mid > 1 ) {
-		MDB_val key;
-		int i;
-		key.mv_size = sizeof(ID);
-		for ( i=1; i<scopes[0].mid; i++ ) {
-			if ( !scopes[i].mval.mv_data )
-				continue;
-			key.mv_data = &scopes[i].mid;
-			mdb_cursor_get( mcd, &key, &scopes[i].mval, MDB_SET );
-		}
-	}
+	key.mv_size = sizeof(ID);
+	if ( ww->mcd ) {	/* scope-based search using dn2id_walk */
+		MDB_val data;
 
-	if ( ww->mcd ) {
-		MDB_val key, data;
+		if ( isc->numrdns )
+			mdb_dn2id_wrestore( op, isc );
 
-		key.mv_size = sizeof(ID);
 		key.mv_data = &ww->key;
 		data = ww->data;
 		rc = mdb_cursor_get( mcd, &key, &data, MDB_GET_BOTH );
@@ -400,6 +392,14 @@ mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd, ID2
 		}
 		op->o_tmpfree( ww->data.mv_data, op->o_tmpmemctx );
 		ww->data.mv_data = NULL;
+	} else if ( isc->scopes[0].mid > 1 ) {	/* candidate-based search */
+		int i;
+		for ( i=1; i<isc->scopes[0].mid; i++ ) {
+			if ( !isc->scopes[i].mval.mv_data )
+				continue;
+			key.mv_data = &isc->scopes[i].mid;
+			mdb_cursor_get( mcd, &key, &isc->scopes[i].mval, MDB_SET );
+		}
 	}
 	return rc;
 }
@@ -1049,7 +1049,7 @@ notfound:
 			rs->sr_ref = NULL;
 
 			if ( wwctx.flag ) {
-				rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, scopes );
+				rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, &isc );
 				if ( rs->sr_err ) {
 					send_ldap_result( op, rs );
 					goto done;
@@ -1111,7 +1111,7 @@ notfound:
 					goto done;
 				}
 				if ( wwctx.flag ) {
-					rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, scopes );
+					rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, &isc );
 					if ( rs->sr_err ) {
 						send_ldap_result( op, rs );
 						goto done;
-- 
2.7.4