]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
marshal: allow to specify null-terminated strings
authorVincent Bernat <bernat@luffy.cx>
Sat, 21 Jan 2012 20:56:20 +0000 (21:56 +0100)
committerVincent Bernat <bernat@luffy.cx>
Sat, 21 Jan 2012 20:56:20 +0000 (21:56 +0100)
src/marshal.c
src/marshal.h
tests/check_marshal.c

index fa62abd4f5aa1efe431b0eed52cd04df4cd75ec9..6dabdcbadd2e6ea928d372ce5d8c841e86cb3c64 100644 (file)
@@ -23,6 +23,12 @@ struct marshal_serialized {
        unsigned char object[0];
 };
 
+struct marshal_info marshal_info__string = {
+       .name = "null string",
+       .size = 0,
+       .pointers = {{ .mi = NULL }},
+};
+
 /* List of already seen pointers */
 struct ref {
        TAILQ_ENTRY(ref) next;
@@ -51,7 +57,13 @@ _marshal_serialize(struct marshal_info *mi, void *unserialized, void **input,
                        return 0;
        }
 
-       size_t len = sizeof(struct marshal_serialized) + (skip?0:mi->size);
+       /* Handle special cases. */
+       int size = mi->size;
+       if (!strcmp(mi->name, "null string"))
+               size = strlen((char *)unserialized) + 1;
+
+       /* Allocate serialized structure */
+       size_t len = sizeof(struct marshal_serialized) + (skip?0:size);
        struct marshal_serialized *serialized = calloc(1, len);
        if (!serialized) {
                LLOG_WARNX("unable to allocate memory to serialize structure %s",
@@ -73,7 +85,7 @@ _marshal_serialize(struct marshal_info *mi, void *unserialized, void **input,
 
        /* First, serialize the main structure */
        if (!skip)
-               memcpy(serialized->object, unserialized, mi->size);
+               memcpy(serialized->object, unserialized, size);
 
        /* Then, serialize inner structures */
        struct marshal_subinfo *current;
@@ -193,15 +205,28 @@ _marshal_unserialize(struct marshal_info *mi, void *buffer, size_t len, void **o
                TAILQ_INIT(pointers);
        }
 
+       /* Special cases */
+       int size = mi->size;
+       if (!strcmp(mi->name, "null string")) {
+               size = strnlen((char *)serialized->object,
+                   len - sizeof(struct marshal_serialized)) + 1;
+               if (size == len - sizeof(struct marshal_serialized) + 1) {
+                       LLOG_WARNX("data to deserialize contains a string too long");
+                       total_len = 0;
+                       goto unmarshal_error;
+               }
+               total_len += size;
+       }
+
        /* First, the main structure */
        if (!skip) {
-               if ((*output = marshal_alloc(pointers, mi->size, serialized->orig)) == NULL) {
+               if ((*output = marshal_alloc(pointers, size, serialized->orig)) == NULL) {
                        LLOG_WARNX("unable to allocate memory to unserialize structure %s",
                            mi->name);
                        total_len = 0;
                        goto unmarshal_error;
                }
-               memcpy(*output, serialized->object, mi->size);
+               memcpy(*output, serialized->object, size);
        }
 
        /* Then, each substructure */
index 55e0a0953d9087fb89f7e50b86416ee099abfc0e..2008603987de94e4ec7eaa75cc3a376cd9396cf5 100644 (file)
@@ -21,6 +21,7 @@ struct marshal_info;
 enum marshal_subinfo_kind {
        pointer,
        substruct,
+       string,
 };
 #define MARSHAL_INFO_POINTER 1
 #define MARSHAL_INFO_SUB     2
@@ -34,6 +35,8 @@ struct marshal_info {
        size_t  size;           /* Size of the structure */
        struct marshal_subinfo pointers[]; /* Pointer to other structures */
 };
+/* Special case for strings */
+extern struct marshal_info marshal_info__string;
 
 /* Declare a new marshal_info struct named after the type we want to
    marshal. The marshalled type has to be a structure. */
@@ -48,6 +51,7 @@ struct marshal_info {
          .mi = &marshal_info_##subtype },
 #define MARSHAL_POINTER(...) MARSHAL_ADD(pointer, ##__VA_ARGS__)
 #define MARSHAL_SUBSTRUCT(...) MARSHAL_ADD(substruct, ##__VA_ARGS__)
+#define MARSHAL_STR(type, member) MARSHAL_ADD(pointer, type, _string, member)
 #define MARSHAL_TQE(type, field)                        \
        MARSHAL_POINTER(type, type, field.tqe_next)      \
        MARSHAL_POINTER(type, type, field.tqe_prev)
index 49e322f8ec39a207e398f37b197d61cbf9034f9e..f4fe66378140272afc1176a2217f53af635a5cd4 100644 (file)
@@ -577,6 +577,41 @@ START_TEST(test_embedded_list) {
 }
 END_TEST
 
+struct struct_string {
+       int s1;
+       char *s2;
+       char *s3;
+};
+MARSHAL_BEGIN(struct_string)
+MARSHAL_STR(struct_string, s2)
+MARSHAL_STR(struct_string, s3)
+MARSHAL_END;
+
+START_TEST(test_string) {
+       struct struct_string source = {
+               .s1 = 44444,
+               .s2 = "String 2",
+               .s3 = "String 3",
+       };
+       struct struct_string *destination;
+       void *buffer;
+       size_t len, len2;
+
+       len = marshal_serialize(struct_string, &source, &buffer);
+       fail_unless(len > 0, "Unable to serialize");
+       memset(&source, 0, sizeof(struct struct_string));
+       len2 = marshal_unserialize(struct_string, buffer, len, &destination);
+       fail_unless(len2 > 0, "Unable to deserialize");
+       free(buffer);
+       ck_assert_int_eq(len, len2);
+       ck_assert_int_eq(destination->s1, 44444);
+       ck_assert_str_eq(destination->s2, "String 2");
+       ck_assert_str_eq(destination->s3, "String 3");
+       free(destination->s2); free(destination->s3);
+       free(destination);
+}
+END_TEST
+
 Suite *
 marshal_suite(void)
 {
@@ -593,6 +628,7 @@ marshal_suite(void)
        tcase_add_test(tc_marshal, test_too_small_unmarshal);
        tcase_add_test(tc_marshal, test_simple_list);
        tcase_add_test(tc_marshal, test_embedded_list);
+       tcase_add_test(tc_marshal, test_string);
        suite_add_tcase(s, tc_marshal);
 
        return s;