]> git.ipfire.org Git - thirdparty/lldpd.git/blobdiff - src/marshal.c
debian: no need to BD on lsb-release anymore
[thirdparty/lldpd.git] / src / marshal.c
index 251a2b50386161c8990f9ec430cd1a5df818487f..0cde547c401266289fdee6f0a56bf645fe6ca8c8 100644 (file)
@@ -15,7 +15,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define _GNU_SOURCE 1
 #define MARSHAL_EXPORT
 #include "marshal.h"
 
 
 #include "lldpd-structs.h"
 
+/* Stolen from CCAN */
+#if HAVE_ALIGNOF
+# define ALIGNOF(t) (__alignof__(t))
+#else
+# define ALIGNOF(t) ((sizeof(t) > 1)?((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0):1)
+#endif
+
 /* A serialized object */
 struct marshal_serialized {
        void         *orig;     /* Original reference. Also enforce alignment. */
@@ -57,7 +63,7 @@ struct marshal_info marshal_info_ignore = {
 struct ref {
        TAILQ_ENTRY(ref) next;
        void *pointer;
-       int dummy;              /* To renumerate pointers */
+       uintptr_t dummy;        /* To renumerate pointers */
 };
 TAILQ_HEAD(ref_l, ref);
 
@@ -72,7 +78,7 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
        size_t len;
        struct marshal_subinfo *current;
        struct marshal_serialized *new = NULL, *serialized = NULL;
-       int dummy = 1;
+       uintptr_t dummy = 1;
 
        log_debug("marshal", "start serialization of %s", mi->name);
 
@@ -95,6 +101,7 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
        /* Handle special cases. */
        size = mi->size;
        if (!strcmp(mi->name, "null string"))
+               /* We know we can't be called with NULL */
                size = strlen((char *)unserialized) + 1;
        else if (!strcmp(mi->name, "fixed string"))
                size = osize;
@@ -109,7 +116,7 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
                goto marshal_error;
        }
        /* We don't use the original pointer but a dummy one. */
-       serialized->orig = (unsigned char*)NULL + dummy;
+       serialized->orig = (unsigned char*)dummy;
 
        /* Append the new reference */
        if (!(cref = calloc(1, sizeof(struct ref)))) {
@@ -129,6 +136,7 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
        /* Then, serialize inner structures */
        for (current = mi->pointers; current->mi; current++) {
                size_t sublen;
+               size_t padlen;
                void  *source;
                void  *target = NULL;
                if (current->kind == ignore) continue;
@@ -141,13 +149,13 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
                        source = (void *)((unsigned char *)unserialized + current->offset);
                if (current->offset2)
                        memcpy(&osize, (unsigned char*)unserialized + current->offset2, sizeof(int));
+               target = NULL;
                sublen = marshal_serialize_(current->mi,
                    source, &target,
                    current->kind == substruct, refs, osize);
-               if (sublen == -1 || target == NULL) {
+               if (sublen == -1) {
                        log_warnx("marshal", "unable to serialize substructure %s for %s",
                            current->mi->name, mi->name);
-                       free(target);
                        free(serialized);
                        return -1;
                }
@@ -155,7 +163,7 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
                if (current->kind == pointer && !skip) {
                        TAILQ_FOREACH(cref, refs, next) {
                                if (source == cref->pointer) {
-                                       void *fakepointer = (unsigned char*)NULL + cref->dummy;
+                                       void *fakepointer = (unsigned char*)cref->dummy;
                                        memcpy((unsigned char *)serialized->object + current->offset,
                                            &fakepointer, sizeof(void *));
                                        break;
@@ -163,8 +171,10 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
                        }
                }
                if (sublen == 0) continue; /* This was already serialized */
-               /* Append the result */
-               new = realloc(serialized, len + sublen);
+               /* Append the result, force alignment to be able to unserialize it */
+               padlen = ALIGNOF(struct marshal_serialized);
+               padlen = (padlen - (len % padlen)) % padlen;
+               new = realloc(serialized, len + padlen + sublen);
                if (!new) {
                        log_warnx("marshal", "unable to allocate more memory to serialize structure %s",
                            mi->name);
@@ -173,9 +183,10 @@ marshal_serialize_(struct marshal_info *mi, void *unserialized, void **input,
                        len = -1;
                        goto marshal_error;
                }
-               memcpy((unsigned char *)new + len, target, sublen);
+               memset((unsigned char *)new + len, 0, padlen);
+               memcpy((unsigned char *)new + len + padlen, target, sublen);
                free(target);
-               len += sublen;
+               len += sublen + padlen;
                serialized = (struct marshal_serialized *)new;
        }
 
@@ -299,6 +310,7 @@ marshal_unserialize_(struct marshal_info *mi, void *buffer, size_t len, void **o
        /* Then, each substructure */
        for (current = mi->pointers; current->mi; current++) {
                size_t  sublen;
+               size_t  padlen;
                new = (unsigned char *)*output + current->offset;
                if (current->kind == ignore) {
                        memset((unsigned char *)*output + current->offset,
@@ -322,10 +334,12 @@ marshal_unserialize_(struct marshal_info *mi, void *buffer, size_t len, void **o
                /* Deserialize */
                if (current->offset2)
                        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, osize);
-               if (sublen == 0) {
+               padlen = ALIGNOF(struct marshal_serialized);
+               padlen = (padlen - (total_len % padlen)) % padlen;
+               if (len < total_len + padlen || ((sublen = marshal_unserialize_(current->mi,
+                               (unsigned char *)buffer + total_len + padlen,
+                               len - total_len - padlen, &new, pointers,
+                               current->kind == substruct, osize)) == 0)) {
                        log_warnx("marshal", "unable to serialize substructure %s for %s",
                            current->mi->name, mi->name);
                        total_len = 0;
@@ -335,7 +349,7 @@ marshal_unserialize_(struct marshal_info *mi, void *buffer, size_t len, void **o
                if (current->kind == pointer)
                        memcpy((unsigned char *)*output + current->offset,
                            &new, sizeof(void *));
-               total_len += sublen;
+               total_len += sublen + padlen;
        }
 
 unmarshal_error: