From 9557a53a9fd1b7bfb5795e5fb818a8165cc4fcb3 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Mon, 7 Oct 2013 09:57:47 -0400
Subject: [PATCH] Ticket 47517 - memory leak in range searches and other various leaks

Bug Description:  Range searches leak memory

Fix Description:  Free the db key, if the key changed between calls to c_get.

                  Also fixed a leak when doing a delete operation(retrieving the
                  parent id), and fixed a leak in replication incremental protocol
                  when getting the hostname control.

https://fedorahosted.org/389/ticket/47517

Reviewed by: ?
---
 ldap/servers/slapd/back-ldbm/idl_new.c     |   16 +++++++++++++++-
 ldap/servers/slapd/back-ldbm/index.c       |    2 --
 ldap/servers/slapd/back-ldbm/ldbm_delete.c |    1 +
 ldap/servers/slapd/ldaputil.c              |    3 ++-
 4 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
index 50ad5cb..f0410f9 100644
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
@@ -576,6 +576,11 @@ idl_new_range_fetch(
         }
 #endif
         ret = cursor->c_get(cursor, &cur_key, &data, DB_NEXT_DUP|DB_MULTIPLE);
+        if (saved_key != cur_key.data) {
+            /* key was allocated in c_get */
+            slapi_ch_free(&saved_key);
+            saved_key = cur_key.data;
+        }
         if (ret) {
             if (upperkey && upperkey->data && DBT_EQ(&cur_key, upperkey)) {
                 /* this is the last key */
@@ -583,6 +588,11 @@ idl_new_range_fetch(
             }
             /* First set the cursor (DB_NEXT_NODUP does not take DB_MULTIPLE) */
             ret = cursor->c_get(cursor, &cur_key, &data, DB_NEXT_NODUP);
+            if (saved_key != cur_key.data) {
+                /* key was allocated in c_get */
+                slapi_ch_free(&saved_key);
+                saved_key = cur_key.data;
+            }
             if (ret) {
                 break;
             }
@@ -633,13 +643,17 @@ idl_new_range_fetch(
             }
         }
         ret = cursor->c_get(cursor,&cur_key,&data,DB_NEXT_DUP);
+        if (saved_key != cur_key.data) {
+            /* key was allocated in c_get */
+            slapi_ch_free(&saved_key);
+            saved_key = cur_key.data;
+        }
         count++;
         if (ret) {
             if (upperkey && upperkey->data && DBT_EQ(&cur_key, upperkey)) {
                 /* this is the last key */
                 break;
             }
-            DBT_FREE_PAYLOAD(cur_key);
             ret = cursor->c_get(cursor, &cur_key, &data, DB_NEXT_NODUP);
             if (saved_key != cur_key.data) {
                 /* key was allocated in c_get */
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index c141800..7189d9f 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -1407,8 +1407,6 @@ index_range_read_ext(
                         type, prefix, *err );
                 }
             } else if (DBTcmp (&upperkey, &cur_key, ai->ai_key_cmp_fn) > 0) {
-                tmpbuf = slapi_ch_realloc (tmpbuf, cur_key.dsize);
-                memcpy (tmpbuf, cur_key.dptr, cur_key.dsize);
                 DBT_FREE_PAYLOAD(upperkey);
                 upperkey.dptr = NULL; /* x >= a :no need to check upper bound */
                 upperkey.dsize = 0;
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index a447435..42e26de 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -457,6 +457,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
 					 * and numsubordinate count could get confused.
 					 */
 					ID pid = (ID)strtol(pid_str, (char **)NULL, 10);
+					slapi_ch_free_string(&pid_str);
 					parent = id2entry(be, pid ,NULL, &retval);
 					if (parent && cache_lock_entry(&inst->inst_cache, parent)) {
 						/* Failed to obtain parent entry's entry lock */
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index f911767..ed3491e 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -1099,6 +1099,7 @@ slapi_ldap_bind(
 	        if (ptr) {
 	            copy = slapi_ch_strdup(myhostname);
 	            *(copy + (ptr - myhostname)) = '\0';
+	            slapi_ch_free_string(&myhostname);
 	            myhostname = copy;
 	        }
 	    }
@@ -1122,7 +1123,7 @@ slapi_ldap_bind(
 			    myerrno ? myerrno : gaierr,
 			    myerrno ? slapd_system_strerror(myerrno) : gai_strerror(gaierr),
 			    myhostname ? myhostname : "unknown host");
-	    slapi_ch_free_string(&copy);
+	    slapi_ch_free_string(&myhostname);
 	    goto done;
 	}
 
-- 
1.7.1

