Explorar o código

Ticket #346 - Fixing memory leaks

Description:
There was a leak in attrlist_replace/attrlist_replace_with_flags
when attr_replace failed to replace the attribute values.

commit 708a56b8d524131362e2d71b7fbc2eb257075e14 for Ticket #47834
tried to fix it, but it was wrong and introduced a double free.
This patch fixes it so that ...
If attr_replace fails and if to be replaced Slapi_Attr is newly
created in attrlist_replace//attrlist_replace_with_flags, the
Slapi_Attr is removed from the attrlist (alist) and Slapi_Attr
is freed.  Otherwise, values and Slapi_Attr are not freed since
Slapi_Attr is just pointing the attribute in the attrlist and
values are consumed in attr_replace.

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

Reviewed by [email protected] (Thank you, Rich!!)
Noriko Hosoi %!s(int64=11) %!d(string=hai) anos
pai
achega
c9b914b161
Modificáronse 1 ficheiros con 14 adicións e 5 borrados
  1. 14 5
      ldap/servers/slapd/attrlist.c

+ 14 - 5
ldap/servers/slapd/attrlist.c

@@ -305,19 +305,20 @@ int attrlist_replace(Slapi_Attr **alist, const char *type, struct berval **vals)
     if (vals == NULL || vals[0] == NULL) {
         (void)attrlist_delete(alist, type);
     } else {
-        attrlist_find_or_create(alist, type, &a);
+        int created = attrlist_find_or_create(alist, type, &a);
         valuearray_init_bervalarray(vals, &values);
         if (slapi_attr_is_dn_syntax_attr(*a)) {
             valuearray_dn_normalize_value(values);
             (*a)->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
         }
-        rc = attr_replace(*a, values);
+        rc = attr_replace(*a, values); /* values is consumed */
         if (rc) {
             slapi_log_error(SLAPI_LOG_FATAL, "attrlist_replace",
                             "attr_replace (%s, %s) failed.\n",
                             type, vals[0]->bv_val);
-            valuearray_free(&values);
-            slapi_attr_free(a);
+            if (created) {
+                attrlist_delete(alist, type);
+            }
         }
     }
     return rc;
@@ -339,13 +340,21 @@ int attrlist_replace_with_flags(Slapi_Attr **alist, const char *type, struct ber
     if (vals == NULL || vals[0] == NULL) {
         (void)attrlist_delete(alist, type);
     } else {
-        attrlist_find_or_create(alist, type, &a);
+        int created = attrlist_find_or_create(alist, type, &a);
         valuearray_init_bervalarray_with_flags(vals, &values, flags);
         if (slapi_attr_is_dn_syntax_attr(*a)) {
             valuearray_dn_normalize_value(values);
             (*a)->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
         }
         rc = attr_replace(*a, values);
+        if (rc) {
+            slapi_log_error(SLAPI_LOG_FATAL, "attrlist_replace",
+                            "attr_replace (%s, %s) failed.\n",
+                            type, vals[0]->bv_val);
+            if (created) {
+                attrlist_delete(alist, type);
+            }
+        }
     }
     return rc;
 }