]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
marshal: handle fixed-size strings
authorVincent Bernat <bernat@luffy.cx>
Sat, 21 Jan 2012 21:42:44 +0000 (22:42 +0100)
committerVincent Bernat <bernat@luffy.cx>
Sat, 21 Jan 2012 21:42:44 +0000 (22:42 +0100)
src/marshal.c
src/marshal.h
tests/check_marshal.c

index 6dabdcbadd2e6ea928d372ce5d8c841e86cb3c64..8a7131fae421345649e68157005dbd8c3723b55f 100644 (file)
@@ -28,6 +28,11 @@ struct marshal_info marshal_info__string = {
        .size = 0,
        .pointers = {{ .mi = NULL }},
 };
+struct marshal_info marshal_info__fstring = {
+       .name = "fixed string",
+       .size = 0,
+       .pointers = {{ .mi = NULL }},
+};
 
 /* List of already seen pointers */
 struct ref {
@@ -39,7 +44,7 @@ TAILQ_HEAD(ref_l, ref);
 /* Serialize the given object. */
 size_t
 _marshal_serialize(struct marshal_info *mi, void *unserialized, void **input,
-    int skip, void *_refs)
+    int skip, void *_refs, int osize)
 {
        /* Check if we have already serialized this one. */
        struct ref_l *refs = _refs;
@@ -61,6 +66,8 @@ _marshal_serialize(struct marshal_info *mi, void *unserialized, void **input,
        int size = mi->size;
        if (!strcmp(mi->name, "null string"))
                size = strlen((char *)unserialized) + 1;
+       else if (!strcmp(mi->name, "fixed string"))
+               size = osize;
 
        /* Allocate serialized structure */
        size_t len = sizeof(struct marshal_serialized) + (skip?0:size);
@@ -98,9 +105,10 @@ _marshal_serialize(struct marshal_info *mi, void *unserialized, void **input,
                        if (source == NULL) continue;
                } else
                        source = (void *)((unsigned char *)unserialized + current->offset);
+               memcpy(&osize, (unsigned char*)unserialized + current->offset2, sizeof(int));
                sublen = _marshal_serialize(current->mi,
                    source, &target,
-                   current->kind == substruct, refs);
+                   current->kind == substruct, refs, osize);
                if (sublen == -1) {
                        LLOG_WARNX("unable to serialize substructure %s for %s",
                            current->mi->name, mi->name);
@@ -184,7 +192,7 @@ marshal_free(struct gc_l *pointers, int gconly)
 /* Unserialize the given object. */
 size_t
 _marshal_unserialize(struct marshal_info *mi, void *buffer, size_t len, void **output,
-    void *_pointers, int skip)
+    void *_pointers, int skip, int osize)
 {
        int    total_len = sizeof(struct marshal_serialized) + (skip?0:mi->size);
        struct marshal_serialized *serialized = buffer;
@@ -207,10 +215,13 @@ _marshal_unserialize(struct marshal_info *mi, void *buffer, size_t len, void **o
 
        /* 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) {
+       if (!strcmp(mi->name, "null string") || !strcmp(mi->name, "fixed string")) {
+               switch (mi->name[0]) {
+               case 'n': size = strnlen((char *)serialized->object,
+                   len - sizeof(struct marshal_serialized)) + 1; break;
+               case 'f': size = osize; break;
+               }
+               if (size > len - sizeof(struct marshal_serialized)) {
                        LLOG_WARNX("data to deserialize contains a string too long");
                        total_len = 0;
                        goto unmarshal_error;
@@ -250,9 +261,10 @@ _marshal_unserialize(struct marshal_info *mi, void *buffer, size_t len, void **o
                        if (already) continue;
                }
                /* Deserialize */
+               memcpy(&osize, (unsigned char *)*output + current->offset2, sizeof(int));
                sublen = _marshal_unserialize(current->mi,
                    (unsigned char *)buffer + total_len, len - total_len, &new, pointers,
-                   current->kind == substruct);
+                   current->kind == substruct, osize);
                if (sublen == 0) {
                        LLOG_WARNX("unable to serialize substructure %s for %s",
                            current->mi->name, mi->name);
index 2008603987de94e4ec7eaa75cc3a376cd9396cf5..cac9e682320e57c4ff7ce6d8a062950bfe29f5e9 100644 (file)
@@ -21,12 +21,12 @@ struct marshal_info;
 enum marshal_subinfo_kind {
        pointer,
        substruct,
-       string,
 };
 #define MARSHAL_INFO_POINTER 1
 #define MARSHAL_INFO_SUB     2
 struct marshal_subinfo {
        size_t offset;       /* Offset compared to parent structure */
+       size_t offset2;      /* Ancillary offset (for related data) */
        enum marshal_subinfo_kind kind; /* Kind of substructure */
        struct  marshal_info *mi;
 };
@@ -37,6 +37,7 @@ struct marshal_info {
 };
 /* Special case for strings */
 extern struct marshal_info marshal_info__string;
+extern struct marshal_info marshal_info__fstring;
 
 /* Declare a new marshal_info struct named after the type we want to
    marshal. The marshalled type has to be a structure. */
@@ -45,13 +46,18 @@ extern struct marshal_info marshal_info__string;
                .name = #type,                                          \
                .size = sizeof(struct type),                            \
                .pointers = {
-#define MARSHAL_ADD(_kind, type, subtype, member)      \
-       { .offset = offsetof(struct type, member),      \
-         .kind = _kind,                                \
+#define MARSHAL_ADD(_kind, type, subtype, member)              \
+       { .offset = offsetof(struct type, member),              \
+         .kind = _kind,                                        \
          .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_FSTR(type, member, len)                                \
+       { .offset = offsetof(struct type, member),              \
+         .offset2 = offsetof(struct type, len),                \
+         .kind = pointer,                                      \
+         .mi = &marshal_info__fstring },
 #define MARSHAL_TQE(type, field)                        \
        MARSHAL_POINTER(type, type, field.tqe_next)      \
        MARSHAL_POINTER(type, type, field.tqe_prev)
@@ -72,12 +78,12 @@ extern struct marshal_info marshal_info__string;
        MARSHAL_END
 
 /* Serialization */
-size_t  _marshal_serialize(struct marshal_info *, void *, void **, int, void *);
-#define marshal_serialize(type, o, output) _marshal_serialize(&marshal_info_##type, o, output, 0, NULL)
+size_t  _marshal_serialize(struct marshal_info *, void *, void **, int, void *, int);
+#define marshal_serialize(type, o, output) _marshal_serialize(&marshal_info_##type, o, output, 0, NULL, 0)
 
 /* Unserialization */
-size_t  _marshal_unserialize(struct marshal_info *, void *, size_t, void **, void*, int);
+size_t  _marshal_unserialize(struct marshal_info *, void *, size_t, void **, void*, int, int);
 #define marshal_unserialize(type, o, l, input) \
-       _marshal_unserialize(&marshal_info_##type, o, l, (void **)input, NULL, 0)
+       _marshal_unserialize(&marshal_info_##type, o, l, (void **)input, NULL, 0, 0)
 
 #endif
index f4fe66378140272afc1176a2217f53af635a5cd4..5d4102c3ac677fcbab0da9df0a35418adade1ac6 100644 (file)
@@ -611,6 +611,48 @@ START_TEST(test_string) {
        free(destination);
 }
 END_TEST
+struct struct_fixedstring {
+       int s1;
+       char *s2;
+       int s2_len;
+       char *s3;
+};
+MARSHAL_BEGIN(struct_fixedstring)
+MARSHAL_FSTR(struct_fixedstring, s2, s2_len)
+MARSHAL_STR(struct_fixedstring, s3)
+MARSHAL_END;
+
+START_TEST(test_fixed_string) {
+       struct struct_fixedstring source = {
+               .s1 = 44444,
+               .s2 = "String 2 Bla",
+               .s2_len = 8,
+               .s3 = "String 3",
+       };
+       struct struct_fixedstring *destination;
+       void *buffer;
+       size_t len, len2;
+
+       len = marshal_serialize(struct_fixedstring, &source, &buffer);
+       fail_unless(len > 0, "Unable to serialize");
+       memset(&source, 0, sizeof(struct struct_string));
+       len2 = marshal_unserialize(struct_fixedstring, 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_int_eq(destination->s2_len, 8);
+       ck_assert_int_eq(destination->s2[0], 'S');
+       ck_assert_int_eq(destination->s2[2], 'r');
+       ck_assert_int_eq(destination->s2[4], 'n');
+       ck_assert_int_eq(destination->s2[5], 'g');
+       ck_assert_int_eq(destination->s2[6], ' ');
+       ck_assert_int_eq(destination->s2[7], '2');
+       ck_assert_str_eq(destination->s3, "String 3");
+       free(destination->s2); free(destination->s3);
+       free(destination);
+}
+END_TEST
 
 Suite *
 marshal_suite(void)
@@ -629,6 +671,7 @@ marshal_suite(void)
        tcase_add_test(tc_marshal, test_simple_list);
        tcase_add_test(tc_marshal, test_embedded_list);
        tcase_add_test(tc_marshal, test_string);
+       tcase_add_test(tc_marshal, test_fixed_string);
        suite_add_tcase(s, tc_marshal);
 
        return s;