[Spice-devel] [PATCH libcacard 07/45] simpletlv: Allow clonning of the SimpleTLV structures with test

Jakub Jelen jjelen at redhat.com
Tue Jul 31 14:50:01 UTC 2018


 * This function creates a deep copy of the whole structure.
 * The new structure is dynamically allocated and needs to be freed.

Signed-off-by: Jakub Jelen <jjelen at redhat.com>
Reviewed-by: Robert Relyea <rrelyea at redhat.com>
---
 src/simpletlv.c   | 42 ++++++++++++++++++++++++++++++++++++++++++
 src/simpletlv.h   |  9 +++++++++
 tests/simpletlv.c | 28 ++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+)

diff --git a/src/simpletlv.c b/src/simpletlv.c
index 5cea04b..2a9a6a7 100644
--- a/src/simpletlv.c
+++ b/src/simpletlv.c
@@ -278,4 +278,46 @@ simpletlv_free(struct simpletlv_member *tlv, size_t tlvlen)
     }
     free(tlv);
 }
+
+struct simpletlv_member *
+simpletlv_clone(struct simpletlv_member *tlv, size_t tlvlen)
+{
+    size_t i = 0, j;
+    struct simpletlv_member *new = NULL;
+
+    new = malloc(sizeof(struct simpletlv_member)*tlvlen);
+    if (!new)
+        goto failure;
+
+    for (i = 0; i < tlvlen; i++) {
+        new[i].type = tlv[i].type;
+        new[i].tag = tlv[i].tag;
+        new[i].length = tlv[i].length;
+        if (tlv[i].type == SIMPLETLV_TYPE_COMPOUND) {
+            new[i].value.child = simpletlv_clone(
+                tlv[i].value.child, tlv[i].length);
+            if (new[i].value.child == NULL)
+                goto failure;
+        } else {
+            new[i].value.value = malloc(
+                sizeof(unsigned char)*tlv[i].length);
+            if (new[i].value.value == NULL)
+                goto failure;
+            memcpy(new[i].value.value, tlv[i].value.value,
+                tlv[i].length);
+        }
+    }
+    return new;
+
+failure:
+    for (j = 0; j < i; i++) {
+        if (tlv[i].type == SIMPLETLV_TYPE_COMPOUND) {
+            simpletlv_free(new[i].value.child, new[i].length);
+        } else {
+            free(new[i].value.value);
+        }
+    }
+    free(new);
+    return NULL;
+}
 /* vim: set ts=4 sw=4 tw=0 noet expandtab: */
diff --git a/src/simpletlv.h b/src/simpletlv.h
index dcb795b..e1cb5a2 100644
--- a/src/simpletlv.h
+++ b/src/simpletlv.h
@@ -115,4 +115,13 @@ int
 simpletlv_read_tag(unsigned char **buf, size_t buflen,
                    unsigned char *tag_out, size_t *taglen);
 
+
+/* create a deep copy of the SimpleTLV structure
+ *
+ * The calling function is responsible for freeing the structure and
+ * all its children by calling simpletlv_free().
+ */
+struct simpletlv_member *
+simpletlv_clone(struct simpletlv_member *tlv, size_t tlvlen);
+
 #endif
diff --git a/tests/simpletlv.c b/tests/simpletlv.c
index 3bd22ae..2be78db 100644
--- a/tests/simpletlv.c
+++ b/tests/simpletlv.c
@@ -220,6 +220,7 @@ static void test_encode_skipped(void)
       {0x30, 2, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_NONE}
     };
     unsigned char encoded[] = "\x25\x02\x12\x14";
+
     simple[0].value.value = simple_value;
     simple[1].value.value = simple_value2;
 
@@ -242,6 +243,32 @@ static void test_encode_skipped(void)
     g_free(result);
 }
 
+static void test_clone_simple(void)
+{
+    unsigned char *result = NULL;
+    size_t result_len = 0;
+    unsigned char simple_value[] = "\x14\x18";
+    unsigned char simple_value2[] = "\x64\x24\x44";
+    static struct simpletlv_member simple[2] = {
+      {0x13, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF},
+      {0xDD, 3, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_LEAF}
+    };
+    unsigned char encoded[] = "\x13\x02\x14\x18\xDD\x03\x64\x24\x44";
+    struct simpletlv_member *clone;
+
+    simple[0].value.value = simple_value;
+    simple[1].value.value = simple_value2;
+
+    clone = simpletlv_clone(simple, 2);
+    g_assert_nonnull(clone);
+
+    result = NULL;
+    result_len = simpletlv_encode(clone, 2, &result, 0, NULL);
+    g_assert_cmpmem(result, result_len, encoded, 9);
+    g_free(result);
+    simpletlv_free(clone, 2);
+}
+
 int main(int argc, char *argv[])
 {
     int ret;
@@ -256,6 +283,7 @@ int main(int argc, char *argv[])
     g_test_add_func("/simpletlv/encode/simple", test_encode_simple);
     g_test_add_func("/simpletlv/encode/nested", test_encode_nested);
     g_test_add_func("/simpletlv/encode/skipped", test_encode_skipped);
+    g_test_add_func("/simpletlv/clone/simple", test_clone_simple);
 
     ret = g_test_run();
 
-- 
2.17.1



More information about the Spice-devel mailing list