andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From c6ffb6173c57228a48f97e935b7f6436a3897063 Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@redhat.com>
dc8c34
Date: Mon, 24 Feb 2014 16:42:36 -0800
dc8c34
Subject: [PATCH 170/225] Ticket #47455 - valgrind - value mem leaks, uninit
dc8c34
 mem usage
dc8c34
dc8c34
Backported the valueset.c part of commit 3adc242bcc8c6d0d05d5d9773f32b4f81afb6e6d.
dc8c34
  Author: Rich Megginson <rmeggins@redhat.com>
dc8c34
dc8c34
  https://fedorahosted.org/389/ticket/47455
dc8c34
  Fix Description: The problem was that slapi_valueset_add_attr_valuearray_ext
dc8c34
  was assuming the caller was going to free the entire given vs upon failure.
dc8c34
  This is fine for the value replace case but not for the add 1 value case.
dc8c34
  Callers of slapi_valueset_add_attr_valuearray_ext must provide
dc8c34
  the dup_index parameter if using SLAPI_VALUE_FLAG_PASSIN and
dc8c34
  SLAPI_VALUE_FLAG_DUPCHECK, and if there is more than one value.  The caller
dc8c34
  needs to know which of the values from addvals is in vs to properly clean up
dc8c34
  with no memory leaks.
dc8c34
  Platforms tested: RHEL6 x86_64
dc8c34
  Flag Day: no
dc8c34
  Doc impact: no
dc8c34
  (cherry picked from commit 3adc242bcc8c6d0d05d5d9773f32b4f81afb6e6d)
dc8c34
  (cherry picked from commit 6357ced2e4380def053966e849eac45e44009662)
dc8c34
(cherry picked from commit 8252d02654cc616beb4558421cd292d470b150cf)
dc8c34
---
dc8c34
 ldap/servers/slapd/valueset.c | 55 +++++++++++++++++++++++++++++++------------
dc8c34
 1 file changed, 40 insertions(+), 15 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
dc8c34
index 4ee2938..29078d4 100644
dc8c34
--- a/ldap/servers/slapd/valueset.c
dc8c34
+++ b/ldap/servers/slapd/valueset.c
dc8c34
@@ -1014,6 +1014,15 @@ valueset_insert_value_to_sorted(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_V
dc8c34
 		
dc8c34
 }
dc8c34
 
dc8c34
+/*
dc8c34
+ * If this function returns an error, it is safe to do both
dc8c34
+ * slapi_valueset_done(vs);
dc8c34
+ * and
dc8c34
+ * valuearray_free(&addvals);
dc8c34
+ * if there is an error and the PASSIN flag is used, the addvals array will own all of the values
dc8c34
+ * vs will own none of the values - so you should do both slapi_valueset_done(vs) and valuearray_free(&add
dc8c34
+ * to clean up
dc8c34
+ */
dc8c34
 int
dc8c34
 slapi_valueset_add_attr_valuearray_ext(const Slapi_Attr *a, Slapi_ValueSet *vs, 
dc8c34
 					Slapi_Value **addvals, int naddvals, unsigned long flags, int *dup_index)
dc8c34
@@ -1086,8 +1095,13 @@ slapi_valueset_add_attr_valuearray_ext(const Slapi_Attr *a, Slapi_ValueSet *vs,
dc8c34
 				if (dup < 0 ) {
dc8c34
 					rc = LDAP_TYPE_OR_VALUE_EXISTS;
dc8c34
 					if (dup_index) *dup_index = i;
dc8c34
-					if ( !passin) 
dc8c34
+					if (passin) {
dc8c34
+						PR_ASSERT((i == 0) || dup_index);
dc8c34
+						/* caller must provide dup_index to know how far we got in addvals */
dc8c34
+						(vs->va)[vs->num] = NULL;
dc8c34
+					} else {
dc8c34
 						slapi_value_free(&(vs->va)[vs->num]);
dc8c34
+					}
dc8c34
 					break;
dc8c34
 				}
dc8c34
 			} else {
dc8c34
@@ -1310,31 +1324,42 @@ valueset_replace_valuearray_ext(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *
dc8c34
 	vs->max = vals_count + 1;
dc8c34
     } else {
dc8c34
 	/* verify the given values are not duplicated.  */
dc8c34
+	unsigned long flags = SLAPI_VALUE_FLAG_PASSIN|SLAPI_VALUE_FLAG_DUPCHECK;
dc8c34
+	int dupindex = 0;
dc8c34
 	Slapi_ValueSet *vs_new = slapi_valueset_new();
dc8c34
-	rc = slapi_valueset_add_attr_valuearray_ext (a, vs_new, valstoreplace, vals_count, 0, NULL);
dc8c34
+	rc = slapi_valueset_add_attr_valuearray_ext (a, vs_new, valstoreplace, vals_count, flags, &dupindex);
dc8c34
 
dc8c34
 	if ( rc == LDAP_SUCCESS )
dc8c34
 	{
dc8c34
+		/* used passin, so vs_new owns all of the Slapi_Value* in valstoreplace
dc8c34
+		 * so tell valuearray_free_ext to start at index vals_count, which is
dc8c34
+		 * NULL, then just free valstoreplace
dc8c34
+		 */
dc8c34
+		valuearray_free_ext(&valstoreplace, vals_count);
dc8c34
 		/* values look good - replace the values in the attribute */
dc8c34
-        	if(!valuearray_isempty(vs->va))
dc8c34
-        	{
dc8c34
-            		/* remove old values */
dc8c34
-            		slapi_valueset_done(vs);
dc8c34
-        	}
dc8c34
-        	vs->va = vs_new->va;
dc8c34
+		if(!valuearray_isempty(vs->va))
dc8c34
+		{
dc8c34
+			/* remove old values */
dc8c34
+			slapi_valueset_done(vs);
dc8c34
+		}
dc8c34
+		vs->va = vs_new->va;
dc8c34
 		vs_new->va = NULL;
dc8c34
-        	vs->sorted = vs_new->sorted;
dc8c34
+		vs->sorted = vs_new->sorted;
dc8c34
 		vs_new->sorted = NULL;
dc8c34
-        	vs->num = vs_new->num;
dc8c34
-        	vs->max = vs_new->max;
dc8c34
+		vs->num = vs_new->num;
dc8c34
+		vs->max = vs_new->max;
dc8c34
 		slapi_valueset_free (vs_new);
dc8c34
 	}
dc8c34
 	else
dc8c34
 	{
dc8c34
-	        /* caller expects us to own valstoreplace - since we cannot
dc8c34
-	           use them, just delete them */
dc8c34
-        	slapi_valueset_free(vs_new);
dc8c34
-        	valuearray_free(&valstoreplace);
dc8c34
+		/* caller expects us to own valstoreplace - since we cannot
dc8c34
+		 use them, just delete them */
dc8c34
+		/* using PASSIN, some of the Slapi_Value* are in vs_new, and the rest
dc8c34
+		 * after dupindex are in valstoreplace
dc8c34
+		 */
dc8c34
+		slapi_valueset_free(vs_new);
dc8c34
+		valuearray_free_ext(&valstoreplace, dupindex);
dc8c34
+		PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
dc8c34
 	}
dc8c34
     }
dc8c34
     return rc;
dc8c34
-- 
dc8c34
1.8.1.4
dc8c34