[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