]> granicus.if.org Git - p11-kit/commitdiff
attrs: New p11_attrs_merge() function
authorStef Walter <stefw@gnome.org>
Thu, 14 Mar 2013 10:23:47 +0000 (11:23 +0100)
committerStef Walter <stefw@gnome.org>
Fri, 15 Mar 2013 16:51:59 +0000 (17:51 +0100)
This takes one set of attributes and merges them into
another, without copying memory needlessly.

https://bugs.freedesktop.org/show_bug.cgi?id=62329

common/attrs.c
common/attrs.h
common/tests/test-attrs.c

index 759bb75702aa73ec7ea88ec1010793482ed1182f..0ccf83283942adb83c13171d27bcee2067bade4d 100644 (file)
@@ -84,7 +84,8 @@ p11_attrs_free (void *attrs)
 static CK_ATTRIBUTE *
 attrs_build (CK_ATTRIBUTE *attrs,
              CK_ULONG count_to_add,
-             bool copy,
+             bool take_values,
+             bool override,
              CK_ATTRIBUTE * (*generator) (void *),
              void *state)
 {
@@ -116,18 +117,28 @@ attrs_build (CK_ATTRIBUTE *attrs,
                for (j = 0; attr == NULL && j < current; j++) {
                        if (attrs[j].type == add->type) {
                                attr = attrs + j;
-                               free (attrs[j].pValue);
                                break;
                        }
                }
 
+               /* The attribute doesn't exist */
                if (attr == NULL) {
                        attr = attrs + at;
                        at++;
+
+               /* The attribute exists and we're not overriding */
+               } else if (!override) {
+                       if (take_values)
+                               free (add->pValue);
+                       continue;
+
+               /* The attribute exitss, and we're overriding */
+               } else {
+                       free (attr->pValue);
                }
 
                memcpy (attr, add, sizeof (CK_ATTRIBUTE));
-               if (copy)
+               if (!take_values)
                        attr->pValue = memdup (attr->pValue, attr->ulValueLen);
        }
 
@@ -158,7 +169,8 @@ p11_attrs_build (CK_ATTRIBUTE *attrs,
        va_end (va);
 
        va_start (va, attrs);
-       attrs = attrs_build (attrs, count, true, vararg_generator, &va);
+       attrs = attrs_build (attrs, count, false, true,
+                            vararg_generator, &va);
        va_end (va);
 
        return attrs;
@@ -176,7 +188,8 @@ p11_attrs_buildn (CK_ATTRIBUTE *attrs,
                   const CK_ATTRIBUTE *add,
                   CK_ULONG count)
 {
-       return attrs_build (attrs, count, true, template_generator, &add);
+       return attrs_build (attrs, count, false, true,
+                           template_generator, &add);
 }
 
 CK_ATTRIBUTE *
@@ -187,7 +200,34 @@ p11_attrs_take (CK_ATTRIBUTE *attrs,
 {
        CK_ATTRIBUTE attr = { type, value, length };
        CK_ATTRIBUTE *add = &attr;
-       return attrs_build (attrs, 1, false, template_generator, &add);
+       return attrs_build (attrs, 1, true, true,
+                           template_generator, &add);
+}
+
+CK_ATTRIBUTE *
+p11_attrs_merge (CK_ATTRIBUTE *attrs,
+                 CK_ATTRIBUTE *merge,
+                 bool replace)
+{
+       CK_ATTRIBUTE *ptr;
+       CK_ULONG count;
+
+       if (attrs == NULL)
+               return merge;
+
+       ptr = merge;
+       count = p11_attrs_count (merge);
+
+       attrs = attrs_build (attrs, count, true, replace,
+                            template_generator, &ptr);
+
+       /*
+        * Since we're supposed to own the merge attributes,
+        * free the container array.
+        */
+       free (merge);
+
+       return attrs;
 }
 
 CK_ATTRIBUTE *
index 870f0d15a640b78213a87c7230373126ef142201..4e3f46cfed9d7c094126aafcb6bf3372beae01a2 100644 (file)
@@ -55,6 +55,10 @@ CK_ATTRIBUTE *      p11_attrs_take          (CK_ATTRIBUTE *attrs,
                                              CK_VOID_PTR value,
                                              CK_ULONG length);
 
+CK_ATTRIBUTE *      p11_attrs_merge         (CK_ATTRIBUTE *attrs,
+                                             CK_ATTRIBUTE *merge,
+                                             bool replace);
+
 bool                p11_attrs_is_empty      (const CK_ATTRIBUTE *attrs);
 
 CK_ULONG            p11_attrs_count         (const CK_ATTRIBUTE *attrs);
index 09d0acefe3da49dcac6847c931f6f132fd1e2947..49350be3dc3ce3de6f00878f4cfe78725d759566 100644 (file)
@@ -290,6 +290,106 @@ test_take (CuTest *tc)
        p11_attrs_free (attrs);
 }
 
+
+static void
+test_merge_replace (CuTest *tc)
+{
+       CK_ATTRIBUTE initial[] = {
+               { CKA_LABEL, "label", 5 },
+               { CKA_VALUE, "nine", 4 },
+       };
+
+       CK_ATTRIBUTE extra[] = {
+               { CKA_LABEL, "boooyah", 7 },
+               { CKA_APPLICATION, "disco", 5 },
+       };
+
+       CK_ATTRIBUTE *attrs;
+       CK_ATTRIBUTE *merge;
+
+       attrs = p11_attrs_buildn (NULL, initial, 2);
+       merge = p11_attrs_buildn (NULL, extra, 2);
+       attrs = p11_attrs_merge (attrs, merge, true);
+       CuAssertPtrNotNull (tc, attrs);
+
+       CuAssertTrue (tc, attrs[0].type == CKA_LABEL);
+       CuAssertIntEquals (tc, 7, attrs[0].ulValueLen);
+       CuAssertTrue (tc, memcmp (attrs[0].pValue, "boooyah", 7) == 0);
+
+       CuAssertPtrNotNull (tc, attrs);
+       CuAssertTrue (tc, attrs[1].type == CKA_VALUE);
+       CuAssertIntEquals (tc, 4, attrs[1].ulValueLen);
+       CuAssertTrue (tc, memcmp (attrs[1].pValue, "nine", 4) == 0);
+
+       CuAssertPtrNotNull (tc, attrs);
+       CuAssertTrue (tc, attrs[2].type == CKA_APPLICATION);
+       CuAssertIntEquals (tc, 5, attrs[2].ulValueLen);
+       CuAssertTrue (tc, memcmp (attrs[2].pValue, "disco", 5) == 0);
+
+       CuAssertTrue (tc, attrs[3].type == CKA_INVALID);
+
+       p11_attrs_free (attrs);
+}
+
+static void
+test_merge_empty (CuTest *tc)
+{
+       CK_ATTRIBUTE extra[] = {
+               { CKA_LABEL, "boooyah", 7 },
+               { CKA_APPLICATION, "disco", 5 },
+       };
+
+       CK_ATTRIBUTE *attrs = NULL;
+       CK_ATTRIBUTE *merge;
+
+       merge = p11_attrs_buildn (NULL, extra, 2);
+       attrs = p11_attrs_merge (attrs, merge, true);
+       CuAssertPtrNotNull (tc, attrs);
+       CuAssertPtrEquals (tc, merge, attrs);
+
+       p11_attrs_free (attrs);
+}
+
+static void
+test_merge_augment (CuTest *tc)
+{
+       CK_ATTRIBUTE initial[] = {
+               { CKA_LABEL, "label", 5 },
+               { CKA_VALUE, "nine", 4 },
+       };
+
+       CK_ATTRIBUTE extra[] = {
+               { CKA_LABEL, "boooyah", 7 },
+               { CKA_APPLICATION, "disco", 5 },
+       };
+
+       CK_ATTRIBUTE *attrs;
+       CK_ATTRIBUTE *merge;
+
+       attrs = p11_attrs_buildn (NULL, initial, 2);
+       merge = p11_attrs_buildn (NULL, extra, 2);
+       attrs = p11_attrs_merge (attrs, merge, false);
+       CuAssertPtrNotNull (tc, attrs);
+
+       CuAssertTrue (tc, attrs[0].type == CKA_LABEL);
+       CuAssertIntEquals (tc, 5, attrs[0].ulValueLen);
+       CuAssertTrue (tc, memcmp (attrs[0].pValue, "label", 5) == 0);
+
+       CuAssertPtrNotNull (tc, attrs);
+       CuAssertTrue (tc, attrs[1].type == CKA_VALUE);
+       CuAssertIntEquals (tc, 4, attrs[1].ulValueLen);
+       CuAssertTrue (tc, memcmp (attrs[1].pValue, "nine", 4) == 0);
+
+       CuAssertPtrNotNull (tc, attrs);
+       CuAssertTrue (tc, attrs[2].type == CKA_APPLICATION);
+       CuAssertIntEquals (tc, 5, attrs[2].ulValueLen);
+       CuAssertTrue (tc, memcmp (attrs[2].pValue, "disco", 5) == 0);
+
+       CuAssertTrue (tc, attrs[3].type == CKA_INVALID);
+
+       p11_attrs_free (attrs);
+}
+
 static void
 test_free_null (CuTest *tc)
 {
@@ -592,6 +692,9 @@ main (void)
        SUITE_ADD_TEST (suite, test_build_null);
        SUITE_ADD_TEST (suite, test_dup);
        SUITE_ADD_TEST (suite, test_take);
+       SUITE_ADD_TEST (suite, test_merge_replace);
+       SUITE_ADD_TEST (suite, test_merge_augment);
+       SUITE_ADD_TEST (suite, test_merge_empty);
        SUITE_ADD_TEST (suite, test_free_null);
        SUITE_ADD_TEST (suite, test_match);
        SUITE_ADD_TEST (suite, test_matchn);