andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From e5d1a517274f6b523c8ed60abe23f899b1967c07 Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@redhat.com>
dc8c34
Date: Thu, 15 May 2014 16:17:00 -0700
dc8c34
Subject: [PATCH 212/225] Ticket #47780 - Some VLV search request causes memory
dc8c34
 leaks
dc8c34
dc8c34
Fix description:
dc8c34
. Modified idl_free interface as follows so that passed idl is cleared
dc8c34
  with NULL once the IDList is successfully freed.
dc8c34
     -idl_free(IDList *idl)
dc8c34
     +idl_free(IDList **idl)
dc8c34
  This change is used to clean up search candidates when ldbm_back_
dc8c34
  search_cleanup (ldbm_search.c) is called as an error return.  The
dc8c34
  cleanup function frees the search candidates when it's not NULL and
dc8c34
  it's not assigned to sr_candidates field in the search result. This
dc8c34
  fixes a memory leak when VLV/Sort op fails.
dc8c34
. ldbm_back_search_cleanup (ldbm_search.c) calls slapi_send_ldap_result
dc8c34
  if an ldap error is passed to the function.  The logic used to be
dc8c34
  "if (ldap_result>=LDAP_SUCCESS)", which is based upon that mozldap
dc8c34
  return codes are all positive.  Supporting openldap library, there
dc8c34
  is a chance to get a negative return code (e.g. LDAP_PARAM_ERROR ==
dc8c34
  -9).  This patch supports the negative return codes, as well.
dc8c34
. In ldbm_back_search (ldbm_search.c) vlv_filter_candidates could
dc8c34
  ruturn errors such as and LDAP_TIMELIMIT_EXCEEDED, LDAP_ADMINLIMIT_
dc8c34
  EXCEEDED.  The search results are supposed to be returned to the
dc8c34
  client with the error code if the control is not critical.  The code
dc8c34
  is added.
dc8c34
. The VLV operation stores the result in vlv_response_control.result
dc8c34
  in ldbm_back_search (ldbm_search.c), which occurs at 3 places, vlv_
dc8c34
  filter_candidates, sort_candidates and vlv_trim_candidates_txn.
dc8c34
  The return code from the latter calls used to override the former
dc8c34
  return code.  This patch fixes it to respect the former return code.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/47780
dc8c34
dc8c34
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
dc8c34
dc8c34
(cherry picked from commit 1118cc9b61a60c704250080d6af8785e4f8d28af)
dc8c34
(cherry picked from commit e9f86dab95fd600b414cf1c4cf6f7c733348b758)
dc8c34
(cherry picked from commit ff4c7a7b3f65589f93d88aadfcbe95976a9b31a9)
dc8c34
(cherry picked from commit bd0fe25aaeea3edda7f4bd0d02d5617791aa058f)
dc8c34
---
dc8c34
 ldap/servers/slapd/back-ldbm/ancestorid.c      |  28 +--
dc8c34
 ldap/servers/slapd/back-ldbm/filterindex.c     |  50 ++---
dc8c34
 ldap/servers/slapd/back-ldbm/idl.c             |  92 ++++-----
dc8c34
 ldap/servers/slapd/back-ldbm/idl_common.c      |  12 +-
dc8c34
 ldap/servers/slapd/back-ldbm/idl_new.c         |   8 +-
dc8c34
 ldap/servers/slapd/back-ldbm/import-merge.c    |   6 +-
dc8c34
 ldap/servers/slapd/back-ldbm/import-threads.c  |   4 +-
dc8c34
 ldap/servers/slapd/back-ldbm/index.c           |  22 +--
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c   |   2 +-
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_modrdn.c     |   4 +-
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_search.c     | 257 ++++++++++++++++---------
dc8c34
 ldap/servers/slapd/back-ldbm/ldif2ldbm.c       |  23 +--
dc8c34
 ldap/servers/slapd/back-ldbm/proto-back-ldbm.h |   2 +-
dc8c34
 ldap/servers/slapd/back-ldbm/seq.c             |   3 +-
dc8c34
 ldap/servers/slapd/back-ldbm/vlv.c             |   2 +-
dc8c34
 15 files changed, 289 insertions(+), 226 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ancestorid.c b/ldap/servers/slapd/back-ldbm/ancestorid.c
dc8c34
index 8722b68..54b08ad 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ancestorid.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ancestorid.c
dc8c34
@@ -136,7 +136,7 @@ static int ldbm_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl)
dc8c34
         LDAPDebug(LDAP_DEBUG_TRACE, "found %lu nodes for ancestorid\n", 
dc8c34
                   (u_long)IDL_NIDS(nodes), 0, 0);
dc8c34
     } else {
dc8c34
-        idl_free(nodes);
dc8c34
+        idl_free(&nodes);
dc8c34
         *idl = NULL;
dc8c34
     }
dc8c34
 
dc8c34
@@ -264,7 +264,7 @@ static int ldbm_ancestorid_default_create_index(backend *be)
dc8c34
         /* Insert into ancestorid for this node */
dc8c34
         if (id2idl_hash_lookup(ht, &id, &ididl)) {
dc8c34
             descendants = idl_union_allids(be, ai_aid, ididl->idl, children);
dc8c34
-            idl_free(children);
dc8c34
+            idl_free(&children);
dc8c34
             if (id2idl_hash_remove(ht, &id) == 0) {
dc8c34
                 LDAPDebug(LDAP_DEBUG_ANY, "ancestorid hash_remove failed\n", 0,0,0);
dc8c34
             } else {
dc8c34
@@ -279,21 +279,21 @@ static int ldbm_ancestorid_default_create_index(backend *be)
dc8c34
         /* Get parentid for this entry */
dc8c34
         ret = ldbm_parentid(be, txn, id, &parentid);
dc8c34
         if (ret != 0) {
dc8c34
-            idl_free(descendants);
dc8c34
+            idl_free(&descendants);
dc8c34
             break;
dc8c34
         }
dc8c34
 
dc8c34
         /* A suffix entry does not have a parent */
dc8c34
         if (parentid == NOID) {
dc8c34
-            idl_free(descendants);
dc8c34
+            idl_free(&descendants);
dc8c34
             continue;
dc8c34
         }
dc8c34
 
dc8c34
         /* Insert into ancestorid for this node's parent */
dc8c34
         if (id2idl_hash_lookup(ht, &parentid, &ididl)) {
dc8c34
             IDList *idl = idl_union_allids(be, ai_aid, ididl->idl, descendants);
dc8c34
-            idl_free(descendants);
dc8c34
-            idl_free(ididl->idl);
dc8c34
+            idl_free(&descendants);
dc8c34
+            idl_free(&(ididl->idl));
dc8c34
             ididl->idl = idl;
dc8c34
         } else {
dc8c34
             ididl = (id2idl*)slapi_ch_calloc(1,sizeof(id2idl));
dc8c34
@@ -324,7 +324,7 @@ static int ldbm_ancestorid_default_create_index(backend *be)
dc8c34
     id2idl_hash_destroy(ht);
dc8c34
 
dc8c34
     /* Free any leftover idlists */
dc8c34
-    idl_free(nodes);
dc8c34
+    idl_free(&nodes);
dc8c34
 
dc8c34
     /* Release the parentid file */
dc8c34
     if (db_pid != NULL) {
dc8c34
@@ -456,7 +456,7 @@ static int ldbm_ancestorid_new_idl_create_index(backend *be)
dc8c34
         /* Insert into ancestorid for this node */
dc8c34
         ret = idl_store_block(be, db_aid, &key, children, txn, ai_aid);
dc8c34
         if (ret != 0) {
dc8c34
-            idl_free(children);
dc8c34
+            idl_free(&children);
dc8c34
             break;
dc8c34
         }
dc8c34
 
dc8c34
@@ -467,13 +467,13 @@ static int ldbm_ancestorid_new_idl_create_index(backend *be)
dc8c34
                 slapi_log_error(SLAPI_LOG_FATAL, sourcefile,
dc8c34
                                 "Error: ldbm_parentid on node index [" ID_FMT "] of [" ID_FMT "]\n",
dc8c34
                                 nids, nodes->b_nids);
dc8c34
-                idl_free(children);
dc8c34
+                idl_free(&children);
dc8c34
                 goto out;
dc8c34
             }
dc8c34
     
dc8c34
             /* A suffix entry does not have a parent */
dc8c34
             if (parentid == NOID) {
dc8c34
-                idl_free(children);
dc8c34
+                idl_free(&children);
dc8c34
                 break;
dc8c34
             }
dc8c34
     
dc8c34
@@ -485,7 +485,7 @@ static int ldbm_ancestorid_new_idl_create_index(backend *be)
dc8c34
             /* Insert into ancestorid for this node's parent */
dc8c34
             ret = idl_store_block(be, db_aid, &key, children, txn, ai_aid);
dc8c34
             if (ret != 0) {
dc8c34
-                idl_free(children);
dc8c34
+                idl_free(&children);
dc8c34
                 goto out;
dc8c34
             }
dc8c34
             id = parentid;
dc8c34
@@ -504,7 +504,7 @@ static int ldbm_ancestorid_new_idl_create_index(backend *be)
dc8c34
     }
dc8c34
 
dc8c34
     /* Free any leftover idlists */
dc8c34
-    idl_free(nodes);
dc8c34
+    idl_free(&nodes);
dc8c34
 
dc8c34
     /* Release the parentid file */
dc8c34
     if (db_pid != NULL) {
dc8c34
@@ -583,7 +583,7 @@ static int ldbm_parentid(backend *be, DB_TXN *txn, ID id, ID *ppid)
dc8c34
 
dc8c34
 static void id2idl_free(id2idl **ididl)
dc8c34
 {
dc8c34
-    idl_free((*ididl)->idl);
dc8c34
+    idl_free(&((*ididl)->idl));
dc8c34
     slapi_ch_free((void**)ididl);
dc8c34
 }
dc8c34
 
dc8c34
@@ -785,7 +785,7 @@ static int ldbm_ancestorid_index_update(
dc8c34
                 break;
dc8c34
             }
dc8c34
             node_id = idl_firstid(idl);
dc8c34
-            idl_free(idl);
dc8c34
+            idl_free(&idl);
dc8c34
         }
dc8c34
 
dc8c34
         /* Update ancestorid for the base entry */
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/filterindex.c b/ldap/servers/slapd/back-ldbm/filterindex.c
dc8c34
index a213815..0998920 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/filterindex.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/filterindex.c
dc8c34
@@ -399,7 +399,7 @@ presence_candidates(
dc8c34
         LDAPDebug(LDAP_DEBUG_TRACE, 
dc8c34
                       "fallback to eq index as pres index gave allids\n", 
dc8c34
                       0, 0, 0);
dc8c34
-        idl_free(idl);
dc8c34
+        idl_free(&idl);
dc8c34
         idl = index_range_read_ext(pb, be, type, indextype_EQUALITY,
dc8c34
                                    SLAPI_OP_GREATER_OR_EQUAL,
dc8c34
                                    NULL, NULL, 0, &txn, err, allidslimit);
dc8c34
@@ -481,7 +481,7 @@ extensible_candidates(
dc8c34
                     else if (keys == NULL || keys[0] == NULL)
dc8c34
                     {
dc8c34
                         /* no keys */
dc8c34
-                        idl_free (idl);
dc8c34
+                        idl_free (&idl);
dc8c34
                         idl = idl_allids (be);
dc8c34
                     }
dc8c34
                     else
dc8c34
@@ -516,8 +516,8 @@ extensible_candidates(
dc8c34
                             else
dc8c34
                             {
dc8c34
                                 IDList* tmp = idl_intersection (be, idl2, idl3);
dc8c34
-                                idl_free (idl2);
dc8c34
-                                idl_free (idl3);
dc8c34
+                                idl_free (&idl2);
dc8c34
+                                idl_free (&idl3);
dc8c34
                                 idl2 = tmp;
dc8c34
                             }
dc8c34
                             if (idl2 == NULL) break; /* look no further */
dc8c34
@@ -529,8 +529,8 @@ extensible_candidates(
dc8c34
                         else if (idl2 != NULL)
dc8c34
                         {
dc8c34
                             IDList* tmp = idl_union (be, idl, idl2);
dc8c34
-                            idl_free (idl);
dc8c34
-                            idl_free (idl2);
dc8c34
+                            idl_free (&idl);
dc8c34
+                            idl_free (&idl2);
dc8c34
                             idl = tmp;
dc8c34
                         }
dc8c34
                     }
dc8c34
@@ -797,7 +797,7 @@ list_candidates(
dc8c34
                 {
dc8c34
                     LDAPDebug( LDAP_DEBUG_TRACE,
dc8c34
                         "<= list_candidates NULL\n", 0, 0, 0 );
dc8c34
-                    idl_free( idl );
dc8c34
+                    idl_free( &idl );
dc8c34
                     idl = NULL;
dc8c34
                     goto out;
dc8c34
                 }
dc8c34
@@ -807,7 +807,7 @@ list_candidates(
dc8c34
                 == NULL && ftype == LDAP_FILTER_AND ) {
dc8c34
                     LDAPDebug( LDAP_DEBUG_TRACE,
dc8c34
                         "<= list_candidates NULL\n", 0, 0, 0 );
dc8c34
-                    idl_free( idl );
dc8c34
+                    idl_free( &idl );
dc8c34
                     idl = NULL;
dc8c34
                     goto out;
dc8c34
             }
dc8c34
@@ -822,18 +822,24 @@ list_candidates(
dc8c34
             }
dc8c34
         } else if ( ftype == LDAP_FILTER_AND ) {
dc8c34
             if (isnot) {
dc8c34
-                IDList *new_idl = NULL;
dc8c34
-                int notin_result = 0;
dc8c34
-                notin_result = idl_notin( be, idl, tmp, &new_idl );
dc8c34
-                if (notin_result) {
dc8c34
-                    idl_free(idl);
dc8c34
-                    idl = new_idl;
dc8c34
+                /*
dc8c34
+                 * If tmp is NULL or ALLID, idl_notin just duplicates idl.
dc8c34
+                 * We don't have to do it.
dc8c34
+                 */
dc8c34
+                if (!tmp && !idl_is_allids(tmp)) {
dc8c34
+                    IDList *new_idl = NULL;
dc8c34
+                    int notin_result = 0;
dc8c34
+                    notin_result = idl_notin( be, idl, tmp, &new_idl );
dc8c34
+                    if (notin_result) {
dc8c34
+                        idl_free(&idl);
dc8c34
+                        idl = new_idl;
dc8c34
+                    }
dc8c34
                 }
dc8c34
             } else {
dc8c34
                 idl = idl_intersection(be, idl, tmp);
dc8c34
-                idl_free( tmp2 );
dc8c34
+                idl_free( &tmp2 );
dc8c34
             }
dc8c34
-            idl_free( tmp );
dc8c34
+            idl_free( &tmp );
dc8c34
             /* stop if the list has gotten too small */
dc8c34
             if ((idl == NULL) ||
dc8c34
                 (idl_length(idl) <= FILTER_TEST_THRESHOLD))
dc8c34
@@ -843,8 +849,8 @@ list_candidates(
dc8c34
             slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
dc8c34
 
dc8c34
             idl = idl_union( be, idl, tmp );
dc8c34
-            idl_free( tmp );
dc8c34
-            idl_free( tmp2 );
dc8c34
+            idl_free( &tmp );
dc8c34
+            idl_free( &tmp2 );
dc8c34
             /* stop if we're already committed to an exhaustive
dc8c34
              * search. :(
dc8c34
              */
dc8c34
@@ -853,7 +859,7 @@ list_candidates(
dc8c34
             if (op_is_pagedresults(operation)) {
dc8c34
                 int nids = IDL_NIDS(idl);
dc8c34
                 if ( allidslimit > 0 && nids > allidslimit ) {
dc8c34
-                    idl_free( idl );
dc8c34
+                    idl_free( &idl );
dc8c34
                     idl = idl_allids( be );
dc8c34
                 }
dc8c34
             }
dc8c34
@@ -976,7 +982,7 @@ keys2idl(
dc8c34
         }
dc8c34
 #endif
dc8c34
         if ( idl2 == NULL ) {
dc8c34
-            idl_free( idl );
dc8c34
+            idl_free( &idl );
dc8c34
             idl = NULL;
dc8c34
             break;
dc8c34
         }
dc8c34
@@ -988,8 +994,8 @@ keys2idl(
dc8c34
 
dc8c34
             tmp = idl;
dc8c34
             idl = idl_intersection(be, idl, idl2);
dc8c34
-            idl_free( idl2 );
dc8c34
-            idl_free( tmp );
dc8c34
+            idl_free( &idl2 );
dc8c34
+            idl_free( &tmp );
dc8c34
             if ( idl == NULL ) {
dc8c34
                 break;
dc8c34
             }
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/idl.c b/ldap/servers/slapd/back-ldbm/idl.c
dc8c34
index 76ee252..67fa711 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/idl.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/idl.c
dc8c34
@@ -280,12 +280,12 @@ idl_old_fetch(
dc8c34
 	if ( ! INDIRECT_BLOCK( idl ) ) {
dc8c34
 		/* make sure we have the current value of highest id */
dc8c34
 		if ( ALLIDS(idl) ) {
dc8c34
-			idl_free( idl );
dc8c34
+			idl_free( &idl );
dc8c34
 			idl = idl_allids( be );
dc8c34
 		}	
dc8c34
 		return( idl );
dc8c34
 	}
dc8c34
-       	idl_free( idl );
dc8c34
+       	idl_free( &idl );
dc8c34
 
dc8c34
 	/* Taking a transaction is expensive; so we try and optimize for the common case by not
dc8c34
 	   taking one above. If we have a indirect block; we need to take a transaction and re-read
dc8c34
@@ -307,7 +307,7 @@ idl_old_fetch(
dc8c34
 		dblayer_read_txn_commit(li,&s_txn);
dc8c34
 		/* make sure we have the current value of highest id */
dc8c34
 		if ( ALLIDS(idl) ) {
dc8c34
-			idl_free( idl );
dc8c34
+			idl_free( &idl );
dc8c34
 			idl = idl_allids( be );
dc8c34
 		}	
dc8c34
 		return( idl );
dc8c34
@@ -367,7 +367,7 @@ idl_old_fetch(
dc8c34
 	dblayer_read_txn_commit(li,&s_txn);	
dc8c34
 	tmp[i] = NULL;
dc8c34
 	slapi_ch_free((void**)&kstr );
dc8c34
-	idl_free( idl );
dc8c34
+	idl_free( &idl );
dc8c34
 
dc8c34
 	/* allocate space for the big block */
dc8c34
 	idl = idl_alloc( nids );
dc8c34
@@ -384,7 +384,7 @@ idl_old_fetch(
dc8c34
 		    tmp[i]->b_nids * sizeof(ID) );
dc8c34
 		nids += tmp[i]->b_nids;
dc8c34
 
dc8c34
-		idl_free( tmp[i] );
dc8c34
+		idl_free( &tmp[i] );
dc8c34
 	}
dc8c34
 	slapi_ch_free((void**)&tmp );
dc8c34
 
dc8c34
@@ -629,7 +629,7 @@ idl_old_insert_key(
dc8c34
 				   rc, (msg = dblayer_strerror( rc )) ? msg : "", 0 );
dc8c34
 		}
dc8c34
 
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 		idl_unlock_list(a->ai_idl,key);
dc8c34
 		return( rc );
dc8c34
 	}
dc8c34
@@ -655,10 +655,10 @@ idl_old_insert_key(
dc8c34
 		case 3:		/* id not inserted - block must be split */
dc8c34
 			/* check threshold for marking this an all-id block */
dc8c34
 			if ( a->ai_idl->idl_maxindirect < 2 ) {
dc8c34
-				idl_free( idl );
dc8c34
+				idl_free( &idl );
dc8c34
 				idl = idl_allids( be );
dc8c34
 				rc = idl_store( be, db, key, idl, txn );
dc8c34
-				idl_free( idl );
dc8c34
+				idl_free( &idl );
dc8c34
 
dc8c34
 				idl_unlock_list(a->ai_idl,key);
dc8c34
 				if ( rc != 0 && rc != DB_LOCK_DEADLOCK)
dc8c34
@@ -673,7 +673,7 @@ idl_old_insert_key(
dc8c34
 			}
dc8c34
 
dc8c34
 			idl_split_block( idl, id, &tmp, &tmp2 );
dc8c34
-			idl_free( idl );
dc8c34
+			idl_free( &idl );
dc8c34
 
dc8c34
 			/* create the header indirect block */
dc8c34
 			idl = idl_alloc( 3 );
dc8c34
@@ -686,9 +686,9 @@ idl_old_insert_key(
dc8c34
 			/* store it */
dc8c34
 			rc = idl_store( be, db, key, idl, txn );
dc8c34
 			if ( rc != 0 ) {
dc8c34
-				idl_free( idl );
dc8c34
-				idl_free( tmp );
dc8c34
-				idl_free( tmp2 );
dc8c34
+				idl_free( &idl );
dc8c34
+				idl_free( &tmp );
dc8c34
+				idl_free( &tmp2 );
dc8c34
 				if ( rc != DB_LOCK_DEADLOCK )
dc8c34
 				{
dc8c34
 					LDAPDebug( LDAP_DEBUG_ANY, "idl_insert_key 3 BAD %d %s\n",
dc8c34
@@ -712,9 +712,9 @@ idl_old_insert_key(
dc8c34
 			k2.dsize = strlen( kstr ) + 1;
dc8c34
 			rc = idl_store( be, db, &k2, tmp2, txn );
dc8c34
 			if ( rc != 0 ) {
dc8c34
-				idl_free( idl );
dc8c34
-				idl_free( tmp );
dc8c34
-				idl_free( tmp2 );
dc8c34
+				idl_free( &idl );
dc8c34
+				idl_free( &tmp );
dc8c34
+				idl_free( &tmp2 );
dc8c34
 				if ( rc != DB_LOCK_DEADLOCK )
dc8c34
 				{
dc8c34
 					LDAPDebug( LDAP_DEBUG_ANY, "idl_insert_key 4 BAD %d %s\n",
dc8c34
@@ -726,12 +726,12 @@ idl_old_insert_key(
dc8c34
 					    "idl_insert_key", "split", key, id);
dc8c34
 
dc8c34
 			slapi_ch_free((void**)&kstr );
dc8c34
-			idl_free( tmp );
dc8c34
-			idl_free( tmp2 );
dc8c34
+			idl_free( &tmp );
dc8c34
+			idl_free( &tmp2 );
dc8c34
 			break;
dc8c34
 		}
dc8c34
 
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 		idl_unlock_list(a->ai_idl,key);
dc8c34
 		if ( rc != 0 && rc != DB_LOCK_DEADLOCK )
dc8c34
 		{
dc8c34
@@ -759,7 +759,7 @@ idl_old_insert_key(
dc8c34
 		    (u_long)id, key.dptr, i);
dc8c34
 #endif
dc8c34
 		idl_unlock_list(a->ai_idl,key);
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 		return( 0 );
dc8c34
 	}
dc8c34
 	if ( i != 0 ) {
dc8c34
@@ -783,7 +783,7 @@ idl_old_insert_key(
dc8c34
 		LDAPDebug( LDAP_DEBUG_ANY,
dc8c34
 		    "nonexistent continuation block (%s)\n", k2.dptr, 0, 0 );
dc8c34
 		idl_unlock_list(a->ai_idl,key);
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 		slapi_ch_free((void**)&kstr );
dc8c34
 		return( -1 );
dc8c34
 	}
dc8c34
@@ -911,9 +911,9 @@ idl_old_insert_key(
dc8c34
 
dc8c34
 				slapi_ch_free( (void **)&(k2.dptr) );
dc8c34
 				slapi_ch_free( (void **)&(k3.dptr) );
dc8c34
-				idl_free( tmp );
dc8c34
-				idl_free( tmp2 );
dc8c34
-				idl_free( idl );
dc8c34
+				idl_free( &tmp );
dc8c34
+				idl_free( &tmp2 );
dc8c34
+				idl_free( &idl );
dc8c34
 				idl_unlock_list(a->ai_idl,key);
dc8c34
 				return( rc );
dc8c34
 
dc8c34
@@ -941,7 +941,7 @@ idl_old_insert_key(
dc8c34
                                  * which is not correct.
dc8c34
                                  */
dc8c34
                                 rc = 0;
dc8c34
-				idl_free( tmp2 );
dc8c34
+				idl_free( &tmp2 );
dc8c34
 				break;
dc8c34
 			}
dc8c34
 			if ( rc != 0 ) {
dc8c34
@@ -986,7 +986,7 @@ idl_old_insert_key(
dc8c34
 
dc8c34
 			/* store allid block in place of header block */
dc8c34
 			if ( 0 == rc ) {
dc8c34
-				idl_free( idl );
dc8c34
+				idl_free( &idl );
dc8c34
 				idl = idl_allids( be );
dc8c34
 				rc = idl_store( be, db, key, idl, txn );
dc8c34
 				if (NULL != disposition) {
dc8c34
@@ -996,14 +996,14 @@ idl_old_insert_key(
dc8c34
 
dc8c34
 			slapi_ch_free( (void **)&(k2.dptr) );
dc8c34
 			slapi_ch_free( (void **)&(k3.dptr) );
dc8c34
-			idl_free( idl );
dc8c34
-			idl_free( tmp );
dc8c34
+			idl_free( &idl );
dc8c34
+			idl_free( &tmp );
dc8c34
 			idl_unlock_list(a->ai_idl,key);
dc8c34
 			return( rc );
dc8c34
 		}
dc8c34
 
dc8c34
 		idl_split_block( tmp, id, &tmp2, &tmp3 );
dc8c34
-		idl_free( tmp );
dc8c34
+		idl_free( &tmp );
dc8c34
 
dc8c34
 		/* create a new updated indirect header block */
dc8c34
 		tmp = idl_alloc( idl->b_nmax + 1 );
dc8c34
@@ -1021,8 +1021,8 @@ idl_old_insert_key(
dc8c34
 		/* store the header block */
dc8c34
 		rc = idl_store( be, db, key, tmp, txn );
dc8c34
 		if ( rc != 0 ) {
dc8c34
-			idl_free( tmp2 );
dc8c34
-			idl_free( tmp3 );
dc8c34
+			idl_free( &tmp2 );
dc8c34
+			idl_free( &tmp3 );
dc8c34
 			break;
dc8c34
 		}
dc8c34
 
dc8c34
@@ -1033,8 +1033,8 @@ idl_old_insert_key(
dc8c34
 		k2.dsize = strlen( kstr ) + 1;
dc8c34
 		rc = idl_store( be, db, &k2, tmp2, txn );
dc8c34
 		if ( rc != 0 ) {
dc8c34
-			idl_free( tmp2 );
dc8c34
-			idl_free( tmp3 );
dc8c34
+			idl_free( &tmp2 );
dc8c34
+			idl_free( &tmp3 );
dc8c34
 			break;
dc8c34
 		}
dc8c34
 
dc8c34
@@ -1045,22 +1045,22 @@ idl_old_insert_key(
dc8c34
 		k2.dsize = strlen( kstr ) + 1;
dc8c34
 		rc = idl_store( be, db, &k2, tmp3, txn );
dc8c34
 		if ( rc != 0 ) {
dc8c34
-			idl_free( tmp2 );
dc8c34
-			idl_free( tmp3 );
dc8c34
+			idl_free( &tmp2 );
dc8c34
+			idl_free( &tmp3 );
dc8c34
 			break;
dc8c34
 		}
dc8c34
 
dc8c34
 		idl_check_indirect (tmp, i, tmp2, tmp3,
dc8c34
 				    "idl_insert_key", "indirect split", key, id);
dc8c34
-		idl_free( tmp2 );
dc8c34
-		idl_free( tmp3 );
dc8c34
+		idl_free( &tmp2 );
dc8c34
+		idl_free( &tmp3 );
dc8c34
 		break;
dc8c34
 	}
dc8c34
 
dc8c34
 	slapi_ch_free( (void **)&(k2.dptr) );
dc8c34
 	slapi_ch_free( (void **)&(k3.dptr) );
dc8c34
-	idl_free( tmp );
dc8c34
-	idl_free( idl );
dc8c34
+	idl_free( &tmp );
dc8c34
+	idl_free( &idl );
dc8c34
 	idl_unlock_list(a->ai_idl,key);
dc8c34
 	return( rc );
dc8c34
 }
dc8c34
@@ -1096,7 +1096,7 @@ int idl_old_store_block(
dc8c34
 			/* If so, store an ALLIDS block */
dc8c34
 			IDList *all = idl_allids(be);
dc8c34
 			ret = idl_store(be,db,key,all,txn);
dc8c34
-			idl_free(all);
dc8c34
+			idl_free(&all;;
dc8c34
 		} else {
dc8c34
 			/* Then , is it a block which is smaller than the size at which it needs splitting ? */
dc8c34
 			if (idl->b_nids <= (ID)priv->idl_maxids) {
dc8c34
@@ -1155,7 +1155,7 @@ int idl_old_store_block(
dc8c34
 					make_cont_key(&cont_key,key,lead_id);
dc8c34
 					/* Now store the continuation block */
dc8c34
 					ret = idl_store(be,db,&cont_key,this_cont_block,txn);
dc8c34
-					idl_free(this_cont_block);
dc8c34
+					idl_free(&this_cont_block);
dc8c34
 					slapi_ch_free(&(cont_key.data));
dc8c34
 					if ( ret != 0 && ret != DB_LOCK_DEADLOCK )
dc8c34
 					{
dc8c34
@@ -1177,7 +1177,7 @@ int idl_old_store_block(
dc8c34
 	}
dc8c34
 done:
dc8c34
 	/* Free master block */
dc8c34
-	idl_free(master_block);
dc8c34
+	idl_free(&master_block);
dc8c34
 	return ret;
dc8c34
 }
dc8c34
 
dc8c34
@@ -1438,7 +1438,7 @@ idl_old_delete_key(
dc8c34
 			break;
dc8c34
 		}
dc8c34
 
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 		idl_unlock_list(a->ai_idl,key);
dc8c34
 		LDAPDebug( LDAP_DEBUG_TRACE, "<= idl_delete_key(%s,%lu) %d (not indirect)\n",
dc8c34
 			   key->dptr, (u_long)id, rc );
dc8c34
@@ -1459,7 +1459,7 @@ idl_old_delete_key(
dc8c34
 	}
dc8c34
 	/* id smaller than smallest id - not there */
dc8c34
 	if ( i == 0 && id < idl->b_ids[i] ) {
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 		idl_unlock_list(a->ai_idl,key);
dc8c34
 		LDAPDebug( LDAP_DEBUG_TRACE, "<= idl_delete_key(%s,%lu) -666 (id not found)\n",
dc8c34
 			   key->dptr, (u_long)id, 0 );
dc8c34
@@ -1472,7 +1472,7 @@ idl_old_delete_key(
dc8c34
 	/* get the block to delete from */
dc8c34
 	make_cont_key( &contkey, key, idl->b_ids[i] );
dc8c34
 	if ( (didl = idl_fetch_one( li, db, &contkey, txn, &rc )) == NULL ) {
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 		idl_unlock_list(a->ai_idl,key);
dc8c34
 		if ( rc != DB_LOCK_DEADLOCK )
dc8c34
 		{
dc8c34
@@ -1559,8 +1559,8 @@ idl_old_delete_key(
dc8c34
 		rc = 0;
dc8c34
 		break;
dc8c34
 	}
dc8c34
-	idl_free( idl );
dc8c34
-	idl_free( didl );
dc8c34
+	idl_free( &idl );
dc8c34
+	idl_free( &didl );
dc8c34
 	slapi_ch_free( (void **)&(contkey.dptr) );
dc8c34
 	idl_unlock_list(a->ai_idl,key);
dc8c34
 	if ( rc != 0 && rc != DB_LOCK_DEADLOCK )
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/idl_common.c b/ldap/servers/slapd/back-ldbm/idl_common.c
dc8c34
index ee59ee2..216bfb0 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/idl_common.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/idl_common.c
dc8c34
@@ -85,13 +85,13 @@ idl_allids( backend *be )
dc8c34
 }
dc8c34
 
dc8c34
 void
dc8c34
-idl_free( IDList *idl ) /* JCM - pass in ** */
dc8c34
+idl_free( IDList **idl )
dc8c34
 {
dc8c34
-	if ( idl == NULL ) {
dc8c34
+	if ((NULL == idl) || (NULL == *idl)) {
dc8c34
 		return;
dc8c34
 	}
dc8c34
 
dc8c34
-	slapi_ch_free((void**)&idl );
dc8c34
+	slapi_ch_free((void**)idl);
dc8c34
 }
dc8c34
 
dc8c34
 
dc8c34
@@ -151,7 +151,7 @@ idl_append_extend(IDList **orig_idl, ID id)
dc8c34
 		/* copy over the existing contents */
dc8c34
 		idl_new->b_nids = idl->b_nids;
dc8c34
 		memcpy(idl_new->b_ids, idl->b_ids, sizeof(ID) * idl->b_nids);
dc8c34
-		idl_free(idl);
dc8c34
+		idl_free(&idl);
dc8c34
 		idl = idl_new;
dc8c34
 	}
dc8c34
 
dc8c34
@@ -243,7 +243,7 @@ idl_intersection(
dc8c34
 	}
dc8c34
 
dc8c34
 	if ( ni == 0 ) {
dc8c34
-		idl_free( n );
dc8c34
+		idl_free( &n );
dc8c34
 		return( NULL );
dc8c34
 	}
dc8c34
 	n->b_nids = ni;
dc8c34
@@ -355,7 +355,7 @@ idl_notin(
dc8c34
 		}
dc8c34
 
dc8c34
 		if ( ni == n->b_nmax ) {
dc8c34
-			idl_free( n );
dc8c34
+			idl_free( &n );
dc8c34
 			*new_result = idl_allids( be );
dc8c34
 		} else {
dc8c34
 			n->b_nids = ni;
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
dc8c34
index 936c19f..1591e84 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
dc8c34
@@ -277,7 +277,7 @@ IDList * idl_new_fetch(
dc8c34
             idl_rc = idl_append_extend(&idl, id);
dc8c34
             if (idl_rc) {
dc8c34
                 LDAPDebug(LDAP_DEBUG_ANY, "unable to extend id list (err=%d)\n", idl_rc, 0, 0);
dc8c34
-                idl_free(idl); idl = NULL;
dc8c34
+                idl_free(&idl);
dc8c34
                 goto error;
dc8c34
             }
dc8c34
 
dc8c34
@@ -314,7 +314,7 @@ IDList * idl_new_fetch(
dc8c34
         idl_rc = idl_append_extend(&idl, id);
dc8c34
         if (idl_rc) {
dc8c34
             LDAPDebug(LDAP_DEBUG_ANY, "unable to extend id list (err=%d)\n", idl_rc);
dc8c34
-            idl_free(idl); idl = NULL;
dc8c34
+            idl_free(&idl);
dc8c34
             goto error;
dc8c34
         }
dc8c34
 #if defined(DB_ALLIDS_ON_READ)	
dc8c34
@@ -330,7 +330,7 @@ IDList * idl_new_fetch(
dc8c34
 #endif
dc8c34
 
dc8c34
     if (ret != DB_NOTFOUND) {
dc8c34
-        idl_free(idl); idl = NULL;
dc8c34
+        idl_free(&idl);
dc8c34
         ldbm_nasty(filename,59,ret);
dc8c34
         goto error;
dc8c34
     }
dc8c34
@@ -339,7 +339,7 @@ IDList * idl_new_fetch(
dc8c34
 
dc8c34
     /* check for allids value */
dc8c34
     if (idl != NULL && idl->b_nids == 1 && idl->b_ids[0] == ALLID) {
dc8c34
-        idl_free(idl);
dc8c34
+        idl_free(&idl);
dc8c34
         idl = idl_allids(be);
dc8c34
         LDAPDebug(LDAP_DEBUG_TRACE, "idl_new_fetch %s returns allids\n", 
dc8c34
                   key.data, 0, 0);
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/import-merge.c b/ldap/servers/slapd/back-ldbm/import-merge.c
dc8c34
index 9d7af3e..e01bf88 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/import-merge.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/import-merge.c
dc8c34
@@ -169,8 +169,8 @@ static int import_merge_insert_input_queue(backend *be, import_merge_queue_entry
dc8c34
                     IDList *new_idl =
dc8c34
                         idl_union(be, current_entry->thang.payload.idl, idl);
dc8c34
 
dc8c34
-                    idl_free(current_entry->thang.payload.idl);
dc8c34
-                    idl_free(idl);
dc8c34
+                    idl_free(&(current_entry->thang.payload.idl));
dc8c34
+                    idl_free(&idl);
dc8c34
                     current_entry->thang.payload.idl = new_idl;
dc8c34
                     /* Add this file id into the entry's referenced list */
dc8c34
                     (current_entry->file_referenced_list)[fileno] = 1;
dc8c34
@@ -567,7 +567,7 @@ static int import_merge_one_file(ImportWorkerInfo *worker, int passes,
dc8c34
 		    ret = idl_store_block(be, output_file, &key,
dc8c34
 			thang.payload.idl, NULL, worker->index_info->ai);
dc8c34
 		    /* Free the key we got back from the queue */
dc8c34
-		    idl_free(thang.payload.idl);
dc8c34
+		    idl_free(&(thang.payload.idl));
dc8c34
 		    thang.payload.idl = NULL;
dc8c34
 		}
dc8c34
 		slapi_ch_free(&(key.data));
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
dc8c34
index e615bb1..44fd35e 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
dc8c34
@@ -2005,7 +2005,7 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
dc8c34
          */
dc8c34
         if (IDL) {
dc8c34
             ID id = idl_firstid(IDL); /* entrydn is a single attr */
dc8c34
-            idl_free(IDL);
dc8c34
+            idl_free(&IDL);
dc8c34
             if (id != entry->ep_id) { /* case (2) */
dc8c34
                 import_log_notice(job, "Duplicated entrydn detected: \"%s\": "
dc8c34
                                        "Entry ID: (%d, %d)",
dc8c34
@@ -2031,7 +2031,7 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
dc8c34
                               "\"%s\" found at line %d of file \"%s\"",
dc8c34
                               slapi_entry_get_dn(entry->ep_entry),
dc8c34
                               fi->line, fi->filename);
dc8c34
-            idl_free(IDL);
dc8c34
+            idl_free(&IDL);
dc8c34
             /* skip this one */
dc8c34
             fi->bad = FIFOITEM_BAD;
dc8c34
             job->skipped++;
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
dc8c34
index 2d5b535..90d1d23 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/index.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/index.c
dc8c34
@@ -197,7 +197,7 @@ index_put_idl(index_buffer_bin *bin,backend *be, DB_TXN *txn,struct attrinfo *a)
dc8c34
 			goto error;
dc8c34
 		}
dc8c34
 		slapi_ch_free( &(bin->key.data) );
dc8c34
-		idl_free(bin->value);
dc8c34
+		idl_free(&(bin->value));
dc8c34
 		/* If we're already at allids, store an allids block to prevent needless accumulation of blocks */
dc8c34
 		if (old_idl && ALLIDS(old_idl)) {
dc8c34
 			bin->value = idl_allids(be);
dc8c34
@@ -207,10 +207,10 @@ index_put_idl(index_buffer_bin *bin,backend *be, DB_TXN *txn,struct attrinfo *a)
dc8c34
 	}
dc8c34
 error:
dc8c34
 	if (old_idl) {
dc8c34
-		idl_free(old_idl);
dc8c34
+		idl_free(&old_idl);
dc8c34
 	}
dc8c34
 	if (new_idl && need_to_freed_new_idl) {
dc8c34
-		idl_free(new_idl);
dc8c34
+		idl_free(&new_idl);
dc8c34
 	}
dc8c34
 	dblayer_release_index_file( be, a, db );
dc8c34
 	return ret;
dc8c34
@@ -268,8 +268,7 @@ index_buffer_terminate(void *h)
dc8c34
 	for (i = 0; i < handle->buffer_size; i++) {
dc8c34
 		bin = &(handle->bins[i]);
dc8c34
 		if (bin->value) {
dc8c34
-			idl_free(bin->value);
dc8c34
-			bin->value = NULL;
dc8c34
+			idl_free(&(bin->value));
dc8c34
 		}
dc8c34
 		slapi_ch_free(&(bin->key.data));
dc8c34
 	}
dc8c34
@@ -1511,9 +1510,7 @@ index_range_read_ext(
dc8c34
         */
dc8c34
         /* Check to see if we've already looked too hard */
dc8c34
         if (idl != NULL && lookthrough_limit != -1 && idl->b_nids > (ID)lookthrough_limit) {
dc8c34
-            if (NULL != idl) {
dc8c34
-                idl_free(idl);
dc8c34
-            }
dc8c34
+            idl_free(&idl);
dc8c34
             idl = idl_allids( be );
dc8c34
             LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read lookthrough_limit exceeded\n",
dc8c34
                                   0, 0, 0);
dc8c34
@@ -1538,10 +1535,7 @@ index_range_read_ext(
dc8c34
          * when the connection is closed by the client).
dc8c34
          */
dc8c34
         if ( slapi_op_abandoned( pb )) {
dc8c34
-            if (NULL != idl) {
dc8c34
-                idl_free(idl);
dc8c34
-                idl = NULL;
dc8c34
-            }
dc8c34
+            idl_free(&idl);
dc8c34
             LDAPDebug(LDAP_DEBUG_TRACE,
dc8c34
                     "index_range_read - operation abandoned\n", 0, 0, 0);
dc8c34
             break;    /* clean up happens outside the while() loop */
dc8c34
@@ -1577,7 +1571,7 @@ index_range_read_ext(
dc8c34
             /* idl tmp only contains one id */
dc8c34
             /* append it at the end here; sort idlist at the end */
dc8c34
             if (ALLIDS(tmp)) {
dc8c34
-                idl_free(idl);
dc8c34
+                idl_free(&idl);
dc8c34
                 idl = tmp;
dc8c34
             } else {
dc8c34
                 ID id;
dc8c34
@@ -1588,7 +1582,7 @@ index_range_read_ext(
dc8c34
                                    1097, *err);
dc8c34
                     }
dc8c34
                 }
dc8c34
-                idl_free(tmp);
dc8c34
+                idl_free(&tmp);
dc8c34
             }
dc8c34
             if (ALLIDS(idl)) {
dc8c34
                 LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read hit an allids value\n",
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
dc8c34
index 38b407d..8369bcc 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
dc8c34
@@ -1090,7 +1090,7 @@ entryrdn_get_subordinates(backend *be,
dc8c34
     
dc8c34
 bail:
dc8c34
     if (rc && subordinates && *subordinates) {
dc8c34
-        idl_free(*subordinates);
dc8c34
+        idl_free(subordinates);
dc8c34
     }
dc8c34
     slapi_ch_free_string(&keybuf);
dc8c34
     slapi_ch_free((void **)&elem);
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
dc8c34
index 4e5ce45..09d8f05 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
dc8c34
@@ -1451,7 +1451,7 @@ common_return:
dc8c34
     slapi_ch_free((void**)&child_dns);
dc8c34
     if (ldap_result_matcheddn && 0 != strcmp(ldap_result_matcheddn, "NULL"))
dc8c34
         slapi_ch_free((void**)&ldap_result_matcheddn);
dc8c34
-    idl_free(children);
dc8c34
+    idl_free(&children);
dc8c34
     slapi_sdn_done(&dn_newdn);
dc8c34
     slapi_sdn_done(&dn_newrdn);
dc8c34
     slapi_sdn_done(&dn_parentdn);
dc8c34
@@ -2170,7 +2170,7 @@ moddn_get_children(back_txn *ptxn,
dc8c34
                 }
dc8c34
             }
dc8c34
         } while (id!=NOID);
dc8c34
-        idl_free(candidates);
dc8c34
+        idl_free(&candidates);
dc8c34
         slapi_sdn_done(&parentsdn);
dc8c34
     }
dc8c34
     
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
index 746528e..626ba2e 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
dc8c34
@@ -46,6 +46,16 @@
dc8c34
 #include "back-ldbm.h"
dc8c34
 #include "vlv_srch.h"
dc8c34
 
dc8c34
+/* 
dc8c34
+ * Used for ldap_result passed to ldbm_back_search_cleanup.
dc8c34
+ * If (ldap_result == LDBM_SRCH_DEFAULT_RESULT) || (ldap_result == LDAP_SUCCESS), 
dc8c34
+ * don't call slapi_send_ldap_result.
dc8c34
+ * Note: mozldap ldap_result codes are all positive; openldap result codes could
dc8c34
+ *       be negative values.  OL (-1) is LDAP_SERVER_DOWN.  Thus, it's safe to 
dc8c34
+ *       borrow the value here.
dc8c34
+ */
dc8c34
+#define LDBM_SRCH_DEFAULT_RESULT (-1)
dc8c34
+
dc8c34
 /* prototypes */
dc8c34
 static int build_candidate_list( Slapi_PBlock *pb, backend *be,
dc8c34
         struct backentry *e, const char * base, int scope,
dc8c34
@@ -160,12 +170,14 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb,
dc8c34
                          char* ldap_result_description,
dc8c34
                          int function_result,
dc8c34
                          struct vlv_request *vlv_request_control,
dc8c34
-                         struct backentry *e)
dc8c34
+                         struct backentry *e,
dc8c34
+                         IDList *candidates)
dc8c34
 {
dc8c34
     int estimate = 0; /* estimated search result count */
dc8c34
     backend *be;
dc8c34
     ldbm_instance *inst;
dc8c34
     back_search_result_set *sr = NULL;
dc8c34
+    int free_candidates = 1;
dc8c34
 
dc8c34
     slapi_pblock_get( pb, SLAPI_BACKEND, &be );
dc8c34
     inst = (ldbm_instance *) be->be_instance_info;
dc8c34
@@ -175,20 +187,27 @@ ldbm_back_search_cleanup(Slapi_PBlock *pb,
dc8c34
     {
dc8c34
         sort_spec_free(sort_control);
dc8c34
     }
dc8c34
-    if(ldap_result>=LDAP_SUCCESS)
dc8c34
-    {
dc8c34
+    if ((ldap_result != LDBM_SRCH_DEFAULT_RESULT) && (ldap_result != LDAP_SUCCESS)) {
dc8c34
         slapi_send_ldap_result( pb, ldap_result, NULL, ldap_result_description, 0, NULL );
dc8c34
     }
dc8c34
     /* code to free the result set if we don't need it */
dc8c34
     /* We get it and check to see if the structure was ever used */
dc8c34
     slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
dc8c34
     if (sr) {
dc8c34
-        if (function_result) {
dc8c34
+        if (function_result) { /* failed case */
dc8c34
             slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
dc8c34
             slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
dc8c34
+            if (sr->sr_candidates == candidates) {
dc8c34
+                free_candidates = 0;
dc8c34
+            }
dc8c34
             delete_search_result_set(pb, &sr);
dc8c34
+        } else if (sr->sr_candidates == candidates) { /* succeeded case */
dc8c34
+            free_candidates = 0;
dc8c34
         }
dc8c34
     }
dc8c34
+    if (free_candidates) {
dc8c34
+        idl_free(&candidates);
dc8c34
+    }
dc8c34
     if (vlv_request_control)
dc8c34
     {
dc8c34
         berval_done(&vlv_request_control->value);
dc8c34
@@ -331,7 +350,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
     back_search_result_set *sr = NULL;
dc8c34
 
dc8c34
     /* Fix for bugid #394184, SD, 20 Jul 00 */
dc8c34
-    int tmp_err = -1;  /* must be lower than LDAP_SUCCESS */
dc8c34
+    int tmp_err = LDBM_SRCH_DEFAULT_RESULT;
dc8c34
     char * tmp_desc = NULL;
dc8c34
     /* end Fix for defect #394184 */
dc8c34
 
dc8c34
@@ -383,9 +402,29 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
             if(r!=0)
dc8c34
             {
dc8c34
                 /* Badly formed SORT control */
dc8c34
-                return ldbm_back_search_cleanup(pb, li, sort_control, 
dc8c34
-                                LDAP_PROTOCOL_ERROR, "Sort Control", 
dc8c34
-                                SLAPI_FAIL_GENERAL, NULL, NULL);
dc8c34
+                if (is_sorting_critical_orig) {
dc8c34
+                    /* RFC 4511 4.1.11 the server must not process the operation
dc8c34
+                     * and return LDAP_UNAVAILABLE_CRITICAL_EXTENSION
dc8c34
+                     */
dc8c34
+                    return ldbm_back_search_cleanup(pb, li, sort_control, 
dc8c34
+                                LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "Sort Control", 
dc8c34
+                                SLAPI_FAIL_GENERAL, NULL, NULL, candidates);
dc8c34
+                } else {
dc8c34
+                    PRUint64 conn_id;
dc8c34
+                    int op_id;
dc8c34
+
dc8c34
+                    /* Just ignore the control */
dc8c34
+                    sort = 0;
dc8c34
+                    slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id);
dc8c34
+                    slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
dc8c34
+
dc8c34
+                    LDAPDebug(LDAP_DEBUG_ANY,
dc8c34
+                            "Warning: Sort control ignored for conn=%d op=%d\n",
dc8c34
+                            conn_id, op_id, 0);                    
dc8c34
+                }
dc8c34
+            } else {
dc8c34
+                /* set this operation includes the server side sorting */
dc8c34
+                operation->o_flags |= OP_FLAG_SERVER_SIDE_SORTING;
dc8c34
             }
dc8c34
             /* set this operation includes the server side sorting */
dc8c34
             operation->o_flags |= OP_FLAG_SERVER_SIDE_SORTING;
dc8c34
@@ -401,30 +440,49 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                 if(r!=LDAP_SUCCESS)
dc8c34
                 {
dc8c34
                     /* Badly formed VLV control */
dc8c34
-                    return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
-                                r, "VLV Control", SLAPI_FAIL_GENERAL, 
dc8c34
-                                &vlv_request_control, NULL);
dc8c34
-                }
dc8c34
-                {
dc8c34
-                    /* Access Control Check to see if the client is allowed to use the VLV Control. */
dc8c34
-                    Slapi_Entry *feature;
dc8c34
-                    char dn[128];
dc8c34
-                    char *dummyAttr = "dummy#attr";
dc8c34
-                    char *dummyAttrs[2] = { NULL, NULL };
dc8c34
-
dc8c34
-                    dummyAttrs[0] = dummyAttr;
dc8c34
-
dc8c34
-                    /* This dn is normalized. */
dc8c34
-                    PR_snprintf(dn,sizeof(dn),"dn: oid=%s,cn=features,cn=config",LDAP_CONTROL_VLVREQUEST);
dc8c34
-                    feature= slapi_str2entry(dn,0);
dc8c34
-                    r= plugin_call_acl_plugin (pb, feature, dummyAttrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL);
dc8c34
-                    slapi_entry_free(feature);
dc8c34
-                    if(r!=LDAP_SUCCESS)
dc8c34
+                    if (is_vlv_critical) {
dc8c34
+                        /* RFC 4511 4.1.11 the server must not process the operation
dc8c34
+                         * and return LDAP_UNAVAILABLE_CRITICAL_EXTENSION
dc8c34
+                         */
dc8c34
+                        return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
+                                LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "VLV Control", SLAPI_FAIL_GENERAL,
dc8c34
+                                &vlv_request_control, NULL, candidates);
dc8c34
+                    } else {
dc8c34
+                        PRUint64 conn_id;
dc8c34
+                        int op_id;
dc8c34
+
dc8c34
+                        /* Just ignore the control */
dc8c34
+                        virtual_list_view = 0;
dc8c34
+                        slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id);
dc8c34
+                        slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
dc8c34
+
dc8c34
+                        LDAPDebug(LDAP_DEBUG_ANY,
dc8c34
+                                "Warning: VLV control ignored for conn=%d op=%d\n",
dc8c34
+                                conn_id, op_id, 0);             
dc8c34
+                    }
dc8c34
+
dc8c34
+                } else {
dc8c34
                     {
dc8c34
-                        /* Client isn't allowed to do this. */
dc8c34
-                        return ldbm_back_search_cleanup(pb, li, sort_control, 
dc8c34
-                                    r, "VLV Control", SLAPI_FAIL_GENERAL, 
dc8c34
-                                    &vlv_request_control, NULL);
dc8c34
+                        /* Access Control Check to see if the client is allowed to use the VLV Control. */
dc8c34
+                        Slapi_Entry *feature;
dc8c34
+                        int rc;
dc8c34
+                        char dn[128];
dc8c34
+                        char *dummyAttr = "dummy#attr";
dc8c34
+                        char *dummyAttrs[2] = {NULL, NULL};
dc8c34
+
dc8c34
+                        dummyAttrs[0] = dummyAttr;
dc8c34
+
dc8c34
+                        /* This dn is normalized. */
dc8c34
+                        PR_snprintf(dn, sizeof (dn), "dn: oid=%s,cn=features,cn=config", LDAP_CONTROL_VLVREQUEST);
dc8c34
+                        feature = slapi_str2entry(dn, 0);
dc8c34
+                        rc = plugin_call_acl_plugin(pb, feature, dummyAttrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL);
dc8c34
+                        slapi_entry_free(feature);
dc8c34
+                        if (rc != LDAP_SUCCESS) {
dc8c34
+                            /* Client isn't allowed to do this. */
dc8c34
+                            return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
+                                    rc, "VLV Control", SLAPI_FAIL_GENERAL,
dc8c34
+                                    &vlv_request_control, NULL, candidates);
dc8c34
+                        }
dc8c34
                     }
dc8c34
                 }
dc8c34
                 /*
dc8c34
@@ -438,7 +496,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                 /* Can't have a VLV control without a SORT control */
dc8c34
                 return ldbm_back_search_cleanup(pb, li, sort_control, 
dc8c34
                                 LDAP_SORT_CONTROL_MISSING, "VLV Control", 
dc8c34
-                                SLAPI_FAIL_GENERAL, &vlv_request_control, NULL);
dc8c34
+                                SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
dc8c34
             }
dc8c34
         }
dc8c34
     }
dc8c34
@@ -491,13 +549,13 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
             {
dc8c34
                 return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                             LDAP_UNWILLING_TO_PERFORM, ctrlstr,
dc8c34
-                            SLAPI_FAIL_GENERAL, &vlv_request_control, NULL);
dc8c34
+                            SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
dc8c34
             }
dc8c34
             else
dc8c34
             {
dc8c34
                 return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                             LDAP_VIRTUAL_LIST_VIEW_ERROR, ctrlstr,
dc8c34
-                            SLAPI_FAIL_GENERAL, &vlv_request_control, NULL);
dc8c34
+                            SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
dc8c34
             }
dc8c34
         }
dc8c34
         else
dc8c34
@@ -512,7 +570,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                 sort_make_sort_response_control(pb, LDAP_UNWILLING_TO_PERFORM, NULL);
dc8c34
                 return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                             LDAP_UNAVAILABLE_CRITICAL_EXTENSION, ctrlstr,
dc8c34
-                            SLAPI_FAIL_GENERAL, &vlv_request_control, NULL);
dc8c34
+                            SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
dc8c34
             }
dc8c34
             else /* vlv and sorting are not critical, so ignore the control */
dc8c34
             {
dc8c34
@@ -546,7 +604,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
         {
dc8c34
             /* error or referral sent by find_entry */
dc8c34
             return ldbm_back_search_cleanup(pb, li, sort_control, 
dc8c34
-                            -1, NULL, 1, &vlv_request_control, NULL);
dc8c34
+                            LDBM_SRCH_DEFAULT_RESULT, NULL, 1, &vlv_request_control, NULL, candidates);
dc8c34
         }
dc8c34
     }
dc8c34
 
dc8c34
@@ -569,6 +627,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
         /*
dc8c34
          * Build a list of IDs for this entry and scope
dc8c34
          */    
dc8c34
+        vlv_response_control.result = LDAP_SUCCESS;
dc8c34
         if ((NULL != controls) && (sort) && (vlv)) {
dc8c34
             /* This candidate list is for vlv, no need for sort only. */
dc8c34
             switch (vlv_search_build_candidate_list(pb, basesdn, &vlv_rc,
dc8c34
@@ -579,12 +638,12 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                 return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                                                 vlv_rc, "VLV Control",
dc8c34
                                                 SLAPI_FAIL_GENERAL, 
dc8c34
-                                                &vlv_request_control, e);
dc8c34
+                                                &vlv_request_control, e, candidates);
dc8c34
             case VLV_BLD_LIST_FAILED:
dc8c34
                 return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                                                 vlv_response_control.result,
dc8c34
                                                 NULL, SLAPI_FAIL_GENERAL,
dc8c34
-                                                &vlv_request_control, e);
dc8c34
+                                                &vlv_request_control, e, candidates);
dc8c34
                 
dc8c34
             case LDAP_SUCCESS:
dc8c34
                 /* Log to the access log the particulars of this sort request */
dc8c34
@@ -605,7 +664,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                                                     LDAP_OPERATIONS_ERROR,
dc8c34
                                                     "Sort Response Control",
dc8c34
                                                     SLAPI_FAIL_GENERAL,
dc8c34
-                                                    &vlv_request_control, e);
dc8c34
+                                                    &vlv_request_control, e, candidates);
dc8c34
                 }
dc8c34
             }
dc8c34
         }
dc8c34
@@ -616,9 +675,9 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
             if (rc)
dc8c34
             {
dc8c34
                 /* Error result sent by build_candidate_list */
dc8c34
-                return ldbm_back_search_cleanup(pb, li, sort_control, -1,
dc8c34
-                                                NULL, rc, 
dc8c34
-                                                &vlv_request_control, e);
dc8c34
+                return ldbm_back_search_cleanup(pb, li, sort_control, 
dc8c34
+                                                LDBM_SRCH_DEFAULT_RESULT, NULL, rc, 
dc8c34
+                                                &vlv_request_control, e, candidates);
dc8c34
             }
dc8c34
             /*
dc8c34
              * If we're sorting then we must check what administrative
dc8c34
@@ -644,25 +703,33 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
              * If we're presenting a virtual list view, then apply the
dc8c34
              * search filter before sorting.
dc8c34
              */
dc8c34
-            if (virtual_list_view && (NULL != candidates))
dc8c34
-            {
dc8c34
-                int r = 0;
dc8c34
+            if (virtual_list_view && candidates) {
dc8c34
                 IDList *idl = NULL;
dc8c34
                 Slapi_Filter *filter = NULL;
dc8c34
                 slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
dc8c34
-                r = vlv_filter_candidates(be, pb, candidates, basesdn,
dc8c34
-                                          scope, filter, &idl,
dc8c34
-                                          lookthrough_limit, time_up);
dc8c34
-                if(r == 0)
dc8c34
-                {
dc8c34
-                    idl_free(candidates);
dc8c34
-                    candidates= idl;
dc8c34
-                }
dc8c34
-                else
dc8c34
-                {
dc8c34
+                rc = vlv_filter_candidates(be, pb, candidates, basesdn,
dc8c34
+                                           scope, filter, &idl,
dc8c34
+                                           lookthrough_limit, time_up);
dc8c34
+                switch (rc) {
dc8c34
+                case LDAP_SUCCESS:  /* Everything OK */
dc8c34
+                case LDAP_TIMELIMIT_EXCEEDED:  /* Timeout */
dc8c34
+                case LDAP_ADMINLIMIT_EXCEEDED:  /* Admin limit exceeded */
dc8c34
+                    vlv_response_control.result = rc;
dc8c34
+                    idl_free(&candidates);
dc8c34
+                    candidates = idl;
dc8c34
+                    break;
dc8c34
+                case LDAP_UNWILLING_TO_PERFORM:  /* Too hard */
dc8c34
+                default: 
dc8c34
                     return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
-                                                    r, NULL, -1, 
dc8c34
-                                                    &vlv_request_control, e);
dc8c34
+                                                    rc, NULL, -1, 
dc8c34
+                                                    &vlv_request_control, e, candidates);
dc8c34
+                }
dc8c34
+                if (is_vlv_critical && rc) {
dc8c34
+                    idl_free(&candidates);
dc8c34
+                    candidates = idl_alloc(0);
dc8c34
+                    tmp_err = rc;
dc8c34
+                    tmp_desc = "VLV Response Control";
dc8c34
+                    goto vlv_bail;
dc8c34
                 }
dc8c34
             }
dc8c34
             /*
dc8c34
@@ -680,7 +747,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                     return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                                              LDAP_PROTOCOL_ERROR,
dc8c34
                                              "Sort Response Control", -1,
dc8c34
-                                             &vlv_request_control, e);
dc8c34
+                                             &vlv_request_control, e, candidates);
dc8c34
                 }
dc8c34
               }
dc8c34
               else
dc8c34
@@ -714,21 +781,24 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                 /* replace the hard coded return value by the appropriate 
dc8c34
                  * LDAP error code */
dc8c34
                 switch (sort_return_value) {
dc8c34
-                   case LDAP_SUCCESS:  /* Everything OK */
dc8c34
-                    vlv_response_control.result= LDAP_SUCCESS;
dc8c34
+                   case LDAP_SUCCESS:
dc8c34
+                    /* 
dc8c34
+                     * we don't want to override an error from vlv 
dc8c34
+                     * vlv_response_control.result= LDAP_SUCCESS; 
dc8c34
+                     */
dc8c34
                     break;
dc8c34
                 case LDAP_PROTOCOL_ERROR:  /* A protocol error */
dc8c34
                     return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                                                     LDAP_PROTOCOL_ERROR,
dc8c34
                                                     "Sort Control", -1,
dc8c34
-                                                    &vlv_request_control, e);
dc8c34
+                                                    &vlv_request_control, e, candidates);
dc8c34
                 case LDAP_UNWILLING_TO_PERFORM:  /* Too hard */
dc8c34
                 case LDAP_OPERATIONS_ERROR:  /* Operation error */
dc8c34
                 case LDAP_TIMELIMIT_EXCEEDED:  /* Timeout */
dc8c34
-                    vlv_response_control.result= LDAP_TIMELIMIT_EXCEEDED;
dc8c34
-                    break;
dc8c34
                 case LDAP_ADMINLIMIT_EXCEEDED:  /* Admin limit exceeded */
dc8c34
-                    vlv_response_control.result = LDAP_ADMINLIMIT_EXCEEDED;
dc8c34
+                    if (!vlv_response_control.result) {
dc8c34
+                        vlv_response_control.result = sort_return_value;
dc8c34
+                    }
dc8c34
                     break;
dc8c34
                 case LDAP_OTHER:  /* Abandoned */
dc8c34
                     abandoned = 1; /* So that we don't return a result code */
dc8c34
@@ -747,11 +817,10 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                 /* Fix for bugid #394184, SD, 05 Jul 00 */
dc8c34
                 /* we were not actually returning unavailableCriticalExtension;
dc8c34
                  now fixed (hopefully !) */
dc8c34
-                if (is_sorting_critical && (0 != sort_return_value))
dc8c34
-                {
dc8c34
-                    idl_free(candidates);
dc8c34
+                if (is_sorting_critical && sort_return_value) {
dc8c34
+                    idl_free(&candidates);
dc8c34
                     candidates = idl_alloc(0);
dc8c34
-                    tmp_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
dc8c34
+                    tmp_err = sort_return_value;
dc8c34
                     tmp_desc = "Sort Response Control";
dc8c34
                 }
dc8c34
                 /* end Fix for bugid #394184 */
dc8c34
@@ -761,9 +830,9 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                                           sort_return_value, sort_error_type ) )
dc8c34
                 {
dc8c34
                     return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
-                                             (abandoned?-1:LDAP_PROTOCOL_ERROR),
dc8c34
+                                             (abandoned?LDBM_SRCH_DEFAULT_RESULT:LDAP_PROTOCOL_ERROR),
dc8c34
                                              "Sort Response Control", -1,
dc8c34
-                                             &vlv_request_control, e);
dc8c34
+                                             &vlv_request_control, e, candidates);
dc8c34
                 }
dc8c34
               }
dc8c34
             }
dc8c34
@@ -771,10 +840,9 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
              * If we're presenting a virtual list view, then the candidate list
dc8c34
              * must be trimmed down to just the range of entries requested.
dc8c34
              */
dc8c34
-            if (virtual_list_view)
dc8c34
-            {
dc8c34
-                if (NULL != candidates && candidates->b_nids>0)
dc8c34
-                {
dc8c34
+            if (virtual_list_view) {
dc8c34
+                if (candidates && (candidates->b_nids > 0) &&
dc8c34
+                    !vlv_response_control.result) {
dc8c34
                     IDList *idl= NULL;
dc8c34
                     back_txn txn = {NULL};
dc8c34
                     slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn);
dc8c34
@@ -783,7 +851,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                         &vlv_request_control, &idl, &vlv_response_control, &txn);
dc8c34
                     if(vlv_response_control.result==0)
dc8c34
                     {
dc8c34
-                        idl_free(candidates);
dc8c34
+                        idl_free(&candidates);
dc8c34
                         candidates = idl;
dc8c34
                     }
dc8c34
                     else
dc8c34
@@ -791,26 +859,23 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
                         return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
                                                     vlv_response_control.result,
dc8c34
                                                     NULL, -1, 
dc8c34
-                                                    &vlv_request_control, e);
dc8c34
+                                                    &vlv_request_control, e, candidates);
dc8c34
                     }
dc8c34
-                }
dc8c34
-                else
dc8c34
-                {
dc8c34
+                } else {
dc8c34
                     vlv_response_control.targetPosition = 0;
dc8c34
                     vlv_response_control.contentCount = 0;
dc8c34
-                    vlv_response_control.result = LDAP_SUCCESS;
dc8c34
+                    /* vlv_response_control.result = LDAP_SUCCESS; Don't override */
dc8c34
                 }
dc8c34
             }
dc8c34
         }
dc8c34
-        if (virtual_list_view)
dc8c34
-        {
dc8c34
-            if(LDAP_SUCCESS != 
dc8c34
-                         vlv_make_response_control( pb, &vlv_response_control ))
dc8c34
-            {
dc8c34
+vlv_bail:
dc8c34
+        if (virtual_list_view) {
dc8c34
+            if (LDAP_SUCCESS != 
dc8c34
+                vlv_make_response_control( pb, &vlv_response_control )) {
dc8c34
                 return ldbm_back_search_cleanup(pb, li, sort_control,
dc8c34
-                                             (abandoned?-1:LDAP_PROTOCOL_ERROR),
dc8c34
+                                             (abandoned?LDBM_SRCH_DEFAULT_RESULT:LDAP_PROTOCOL_ERROR),
dc8c34
                                              "VLV Response Control", -1,
dc8c34
-                                             &vlv_request_control, e);
dc8c34
+                                             &vlv_request_control, e, candidates);
dc8c34
             }
dc8c34
             /* Log the VLV operation */
dc8c34
             vlv_print_access_log(pb,&vlv_request_control,&vlv_response_control);
dc8c34
@@ -840,7 +905,7 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
             PR_Unlock(inst->inst_config_mutex);
dc8c34
 
dc8c34
             if (ri) {
dc8c34
-                idl_free(candidates);
dc8c34
+                idl_free(&candidates);
dc8c34
                 candidates = idl_alloc(0);
dc8c34
                 tmp_err = LDAP_UNWILLING_TO_PERFORM;
dc8c34
                 tmp_desc = "Search is not indexed";
dc8c34
@@ -903,10 +968,10 @@ ldbm_back_search( Slapi_PBlock *pb )
dc8c34
     }
dc8c34
 
dc8c34
     /* Fix for bugid #394184, SD, 05 Jul 00 */
dc8c34
-    /* tmp_err == -1: no error */
dc8c34
+    /* tmp_err == LDBM_SRCH_DEFAULT_RESULT: no error */
dc8c34
     return ldbm_back_search_cleanup(pb, li, sort_control, tmp_err, tmp_desc,
dc8c34
-                                    (tmp_err  == -1 ? 0 : -1), 
dc8c34
-                                    &vlv_request_control, NULL);
dc8c34
+                                    (tmp_err == LDBM_SRCH_DEFAULT_RESULT ? 0 : LDBM_SRCH_DEFAULT_RESULT), 
dc8c34
+                                    &vlv_request_control, NULL, candidates);
dc8c34
     /* end Fix for bugid #394184 */
dc8c34
 }
dc8c34
 
dc8c34
@@ -1167,14 +1232,14 @@ subtree_candidates(
dc8c34
                                          e->ep_id, &descendants, &txn, 0);
dc8c34
             idl_insert(&descendants, e->ep_id);
dc8c34
             candidates = idl_intersection(be, candidates, descendants);
dc8c34
-            idl_free(tmp);
dc8c34
-            idl_free(descendants);
dc8c34
+            idl_free(&tmp);
dc8c34
+            idl_free(&descendants);
dc8c34
         } else if (!has_tombstone_filter) {
dc8c34
             *err = ldbm_ancestorid_read_ext(be, &txn, e->ep_id, &descendants, allidslimit);
dc8c34
             idl_insert(&descendants, e->ep_id);
dc8c34
             candidates = idl_intersection(be, candidates, descendants);
dc8c34
-            idl_free(tmp);
dc8c34
-            idl_free(descendants);
dc8c34
+            idl_free(&tmp);
dc8c34
+            idl_free(&descendants);
dc8c34
         } /* else == has_tombstone_filter: do nothing */
dc8c34
     }
dc8c34
 
dc8c34
@@ -1802,7 +1867,7 @@ delete_search_result_set( Slapi_PBlock *pb, back_search_result_set **sr )
dc8c34
     }
dc8c34
     if ( NULL != (*sr)->sr_candidates )
dc8c34
     {
dc8c34
-        idl_free( (*sr)->sr_candidates );
dc8c34
+        idl_free( &((*sr)->sr_candidates) );
dc8c34
     }
dc8c34
     rc = slapi_filter_apply((*sr)->sr_norm_filter, ldbm_search_free_compiled_filter,
dc8c34
                             NULL, &filt_errs);
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
dc8c34
index 51ff62b..76eea2c 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
dc8c34
@@ -291,7 +291,7 @@ int add_op_attrs(Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *ep,
dc8c34
             if ( (idl = index_read( be, LDBM_ENTRYDN_STR, indextype_EQUALITY, 
dc8c34
                                     &bv, NULL, &err )) != NULL ) {
dc8c34
                 pid = idl_firstid( idl );
dc8c34
-                idl_free( idl );
dc8c34
+                idl_free( &idl );
dc8c34
             } else {
dc8c34
                 /* empty idl */
dc8c34
                 if ( 0 != err && DB_NOTFOUND != err ) {
dc8c34
@@ -591,7 +591,7 @@ int update_subordinatecounts(backend *be, import_subcount_stuff *mothers,
dc8c34
                     /* We get the count from the IDL */
dc8c34
                     sub_count = idl->b_nids;
dc8c34
                 }
dc8c34
-                idl_free(idl);
dc8c34
+                idl_free(&idl);
dc8c34
             } 
dc8c34
             /* Did we get the count ? */
dc8c34
             if (found_count) {
dc8c34
@@ -889,8 +889,7 @@ static IDList *ldbm_fetch_subtrees(backend *be, char **include, int *err)
dc8c34
                 continue;
dc8c34
             }
dc8c34
             id = idl_firstid(idl);
dc8c34
-            idl_free(idl);
dc8c34
-            idl = NULL;
dc8c34
+            idl_free(&idl);
dc8c34
         }
dc8c34
 
dc8c34
         /*
dc8c34
@@ -928,8 +927,8 @@ static IDList *ldbm_fetch_subtrees(backend *be, char **include, int *err)
dc8c34
             idltotal = idl;
dc8c34
         } else if (idl) {
dc8c34
             idltmp = idl_union(be, idltotal, idl);
dc8c34
-            idl_free(idltotal);
dc8c34
-            idl_free(idl);
dc8c34
+            idl_free(&idltotal);
dc8c34
+            idl_free(&idl);
dc8c34
             idltotal = idltmp;
dc8c34
         }
dc8c34
     } /* for (i = 0; include[i]; i++) */
dc8c34
@@ -1331,8 +1330,7 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb )
dc8c34
             /* allids list is no help at all -- revert to trawling
dc8c34
              * the whole list. */
dc8c34
             ok_index = 0;
dc8c34
-            idl_free(idl);
dc8c34
-            idl = NULL;
dc8c34
+            idl_free(&idl);
dc8c34
         }
dc8c34
         idindex = 0;
dc8c34
     }
dc8c34
@@ -1588,7 +1586,7 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb )
dc8c34
     }
dc8c34
 bye:
dc8c34
     if (idl) {
dc8c34
-        idl_free(idl);
dc8c34
+        idl_free(&idl);
dc8c34
     }
dc8c34
     if (dbc) {
dc8c34
         dbc->c_close(dbc);
dc8c34
@@ -1619,7 +1617,7 @@ bye:
dc8c34
     }
dc8c34
 
dc8c34
     ldbm_back_free_incl_excl(include_suffix, exclude_suffix);
dc8c34
-    idl_free(eargs.pre_exported_idl);
dc8c34
+    idl_free(&(eargs.pre_exported_idl));
dc8c34
     
dc8c34
     return( return_value );
dc8c34
 }
dc8c34
@@ -1933,8 +1931,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
dc8c34
             }
dc8c34
         } else if (ALLIDS(idl)) {
dc8c34
             /* that's no help. */
dc8c34
-            idl_free(idl);
dc8c34
-            idl = NULL;
dc8c34
+            idl_free(&idl);
dc8c34
         }
dc8c34
     }
dc8c34
 
dc8c34
@@ -2443,7 +2440,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
dc8c34
 err_out:
dc8c34
     backentry_free( &ep ); /* if ep or *ep is NULL, it does nothing */
dc8c34
     if (idl) {
dc8c34
-        idl_free(idl);
dc8c34
+        idl_free(&idl);
dc8c34
     } else {
dc8c34
         dbc->c_close(dbc);
dc8c34
     }
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
index f3c84a1..499c92b 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
@@ -232,7 +232,7 @@ struct backentry * id2entry( backend *be, ID id, back_txn *txn, int *err );
dc8c34
  * idl.c
dc8c34
  */
dc8c34
 IDList * idl_alloc( NIDS nids );
dc8c34
-void idl_free( IDList *idl );
dc8c34
+void idl_free( IDList **idl );
dc8c34
 NIDS idl_length(IDList *idl);
dc8c34
 int idl_is_allids(IDList *idl);
dc8c34
 int idl_append(IDList *idl, ID id);
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/seq.c b/ldap/servers/slapd/back-ldbm/seq.c
dc8c34
index ab473bd..a947438 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/seq.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/seq.c
dc8c34
@@ -235,6 +235,7 @@ ldbm_back_seq( Slapi_PBlock *pb )
dc8c34
 				key.flags = 0;
dc8c34
 				for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) {
dc8c34
 				  err = NEW_IDL_DEFAULT;
dc8c34
+				  idl_free(&idl);
dc8c34
 				  idl = idl_fetch( be, db, &key, NULL, ai, &err );
dc8c34
 				  if(err == DB_LOCK_DEADLOCK) {
dc8c34
 				    ldbm_nasty("ldbm_back_seq deadlock retry", 1600, err);
dc8c34
@@ -289,7 +290,7 @@ ldbm_back_seq( Slapi_PBlock *pb )
dc8c34
 		    }
dc8c34
 		    CACHE_RETURN( &inst->inst_cache, &e );
dc8c34
 		}
dc8c34
-		idl_free( idl );
dc8c34
+		idl_free( &idl );
dc8c34
 	}
dc8c34
 
dc8c34
 	dblayer_release_index_file( be, ai, db );
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/vlv.c b/ldap/servers/slapd/back-ldbm/vlv.c
dc8c34
index dcc42fa..ad38889 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/vlv.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/vlv.c
dc8c34
@@ -1112,7 +1112,7 @@ int vlv_build_idl(PRUint32 start, PRUint32 stop, DB *db, DBC *dbc,
dc8c34
     goto done;
dc8c34
 
dc8c34
 error:
dc8c34
-    if (idl) idl_free(idl);
dc8c34
+    if (idl) idl_free(&idl);
dc8c34
 
dc8c34
 done:
dc8c34
     return rc;
dc8c34
-- 
dc8c34
1.8.1.4
dc8c34