]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
marshal: respect GCC strict-aliasing rule
authorVincent Bernat <bernat@luffy.cx>
Sun, 23 Dec 2012 12:08:26 +0000 (13:08 +0100)
committerVincent Bernat <bernat@luffy.cx>
Sun, 23 Dec 2012 12:19:52 +0000 (13:19 +0100)
Strict-aliasing states that when a derefencing pointers to objects of
different types will never refer to the same memory location. A
complete explanation is available here:
 http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html

While `void*` is a special kind, `void**` is not. Therefore, we
respect strict-aliasing by using an intermediate variable.

src/daemon/client.c
src/lib/atom.c
src/lib/connection.c
src/marshal.h
tests/check_marshal.c

index e48216e4277534090e60bf826e31776bf6009de8..87059e62b1a6a2001c6ea2693f9733f768d21b88 100644 (file)
@@ -47,13 +47,15 @@ client_handle_set_configuration(struct lldpd *cfg, enum hmsg_type *type,
     void *input, int input_len, void **output, int *subscribed)
 {
        struct lldpd_config *config;
+       void *p;
 
        log_debug("rpc", "client request a change in configuration");
        /* Get the proposed configuration. */
-       if (marshal_unserialize(lldpd_config, input, input_len, &config) <= 0) {
+       if (marshal_unserialize(lldpd_config, input, input_len, &p) <= 0) {
                *type = NONE;
                return 0;
        }
+       config = p;
 
        /* What needs to be done? Currently, we only support setting the
         * transmit delay. */
@@ -124,13 +126,15 @@ client_handle_get_interface(struct lldpd *cfg, enum hmsg_type *type,
     void *input, int input_len, void **output, int *subscribed)
 {
        char *name;
+       void *p;
        struct lldpd_hardware *hardware;
 
        /* Get name of the interface */
-       if (marshal_unserialize(string, input, input_len, &name) <= 0) {
+       if (marshal_unserialize(string, input, input_len, &p) <= 0) {
                *type = NONE;
                return 0;
        }
+       name = p;
 
        /* Search appropriate hardware */
        log_debug("rpc", "client request interface %s", name);
@@ -161,16 +165,18 @@ client_handle_set_port(struct lldpd *cfg, enum hmsg_type *type,
     void *input, int input_len, void **output, int *subscribed)
 {
        int ret = 0;
+       void *p;
        struct lldpd_port_set *set = NULL;
        struct lldpd_hardware *hardware = NULL;
 #ifdef ENABLE_LLDPMED
        struct lldpd_med_loc *loc = NULL;
 #endif
 
-       if (marshal_unserialize(lldpd_port_set, input, input_len, &set) <= 0) {
+       if (marshal_unserialize(lldpd_port_set, input, input_len, &p) <= 0) {
                *type = NONE;
                return 0;
        }
+       set = p;
        if (!set->ifname) {
                log_warnx("rpc", "no interface provided");
                goto set_port_finished;
index 2e3586b33fb86de45acd281a89b592b61cc167b2..1486b1faa94cdb1657a16d4cff205345b0604e63 100644 (file)
@@ -395,6 +395,7 @@ lldpctl_get_configuration(lldpctl_conn_t *conn)
 {
        int rc;
        struct lldpd_config *config;
+       void *p;
 
        RESET_ERROR(conn);
 
@@ -402,9 +403,11 @@ lldpctl_get_configuration(lldpctl_conn_t *conn)
            CONN_STATE_GET_CONFIG_SEND, CONN_STATE_GET_CONFIG_RECV, NULL,
            GET_CONFIG,
            NULL, NULL,
-           (void **)&config, &MARSHAL_INFO(lldpd_config));
-       if (rc == 0)
+           &p, &MARSHAL_INFO(lldpd_config));
+       if (rc == 0) {
+               config = p;
                return _lldpctl_new_atom(conn, atom_config, config);
+       }
        return NULL;
 }
 
@@ -412,6 +415,7 @@ lldpctl_atom_t*
 lldpctl_get_interfaces(lldpctl_conn_t *conn)
 {
        struct lldpd_interface_list *ifs;
+       void *p;
        int rc;
 
        RESET_ERROR(conn);
@@ -420,9 +424,11 @@ lldpctl_get_interfaces(lldpctl_conn_t *conn)
            CONN_STATE_GET_INTERFACES_SEND, CONN_STATE_GET_INTERFACES_RECV, NULL,
            GET_INTERFACES,
            NULL, NULL,
-           (void **)&ifs, &MARSHAL_INFO(lldpd_interface_list));
-       if (rc == 0)
+           &p, &MARSHAL_INFO(lldpd_interface_list));
+       if (rc == 0) {
+               ifs = p;
                return _lldpctl_new_atom(conn, atom_interfaces_list, ifs);
+       }
        return NULL;
 }
 
@@ -432,6 +438,7 @@ lldpctl_get_port(lldpctl_atom_t *atom)
        int rc;
        lldpctl_conn_t *conn = atom->conn;
        struct lldpd_hardware *hardware;
+       void *p;
        struct _lldpctl_atom_interface_t *iface =
            (struct _lldpctl_atom_interface_t *)atom;
 
@@ -444,9 +451,11 @@ lldpctl_get_port(lldpctl_atom_t *atom)
        rc = _lldpctl_do_something(conn,
            CONN_STATE_GET_PORT_SEND, CONN_STATE_GET_PORT_RECV, iface->name,
            GET_INTERFACE, (void*)iface->name, &MARSHAL_INFO(string),
-           (void**)&hardware, &MARSHAL_INFO(lldpd_hardware));
-       if (rc == 0)
+           &p, &MARSHAL_INFO(lldpd_hardware));
+       if (rc == 0) {
+               hardware = p;
                return _lldpctl_new_atom(conn, atom_port,
                    hardware, &hardware->h_lport, NULL);
+       }
        return NULL;
 }
index 1aa3d370119b46537e2aa83a5debb0e40f238602..405cce18b1f7243ff5af503644153285887c39ff 100644 (file)
@@ -166,15 +166,17 @@ static void
 check_for_notification(lldpctl_conn_t *conn)
 {
        struct lldpd_neighbor_change *change;
+       void *p;
        int rc;
        lldpctl_change_t type;
        lldpctl_atom_t *interface = NULL, *neighbor = NULL;
        rc = ctl_msg_recv_unserialized(&conn->input_buffer,
            &conn->input_buffer_len,
            NOTIFICATION,
-           (void**)&change,
+           &p,
            &MARSHAL_INFO(lldpd_neighbor_change));
        if (rc != 0) return;
+       change = p;
 
        /* We have a notification, call the callback */
        if (conn->watch_cb) {
index 4f6da2acfbd59dd01bd42277a933759d8b69e509..eed7c9f2ba03a6828642b5b30b947947ffa9d85c 100644 (file)
@@ -112,6 +112,6 @@ size_t  marshal_serialize_(struct marshal_info *, void *, void **, int, void *,
 /* Unserialization */
 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, 0)
+       marshal_unserialize_(&MARSHAL_INFO(type), o, l, input, NULL, 0, 0)
 
 #endif
index f6d14dd820ab6b1dee5a21aac6d8146954214608..3dd4f649bd88476a3b9f4e2ebe9c505f23baa4ce 100644 (file)
@@ -33,14 +33,16 @@ START_TEST(test_simple_structure) {
                .a5 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G'},
        };
        struct struct_simple *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
 
        len = marshal_serialize(struct_simple, &source, &buffer);
        fail_unless(len > 0, "Unable to serialize");
        memset(&source, 0, sizeof(struct struct_simple));
-       len2 = marshal_unserialize(struct_simple, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_simple, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
+       destination = p;
        free(buffer);
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->a1, 78452);
@@ -81,15 +83,17 @@ START_TEST(test_substruct_structure) {
        };
 
        struct struct_sub *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
 
        len = marshal_serialize(struct_sub, &source, &buffer);
        fail_unless(len > 0, "Unable to serialize");
        memset(&source, 0, sizeof(struct struct_sub));
-       len2 = marshal_unserialize(struct_sub, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_sub, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->e1, -5122);
        ck_assert_int_eq(destination->e2.a1, 78452);
@@ -136,6 +140,7 @@ START_TEST(test_pointer_structure) {
        };
 
        struct struct_onepointer *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
 
@@ -143,9 +148,10 @@ START_TEST(test_pointer_structure) {
        fail_unless(len > 0, "Unable to serialize");
        memset(&source_simple, 0, sizeof(struct struct_simple));
        memset(&source, 0, sizeof(struct struct_onepointer));
-       len2 = marshal_unserialize(struct_onepointer, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_onepointer, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->b1, 18);
        ck_assert_int_eq(destination->b2, 15454);
@@ -209,6 +215,7 @@ START_TEST(test_several_pointers_structure) {
        };
 
        struct struct_nestedpointers *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
 
@@ -218,9 +225,10 @@ START_TEST(test_several_pointers_structure) {
        memset(&source_simple2, 0, sizeof(struct struct_simple));
        memset(&source_onepointer, 0, sizeof(struct struct_onepointer));
        memset(&source, 0, sizeof(struct struct_nestedpointers));
-       len2 = marshal_unserialize(struct_nestedpointers, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_nestedpointers, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->c1, 4542);
        ck_assert_int_eq(destination->c2, 5665454);
@@ -268,6 +276,7 @@ START_TEST(test_null_pointers) {
        };
 
        struct struct_nestedpointers *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
 
@@ -275,9 +284,10 @@ START_TEST(test_null_pointers) {
        fail_unless(len > 0, "Unable to serialize");
        memset(&source_simple2, 0, sizeof(struct struct_simple));
        memset(&source, 0, sizeof(struct struct_nestedpointers));
-       len2 = marshal_unserialize(struct_nestedpointers, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_nestedpointers, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->c1, 4542);
        ck_assert_int_eq(destination->c2, 5665454);
@@ -325,6 +335,7 @@ START_TEST(test_multiple_references) {
        };
 
        struct struct_multipleref *destination;
+       void *p;
        void *buffer = NULL;
        size_t len, len2;
 
@@ -334,9 +345,10 @@ START_TEST(test_multiple_references) {
        memset(&source_simple, 0, sizeof(struct struct_simple));
        memset(&source_nested, 0, sizeof(struct struct_nestedpointers));
        memset(&source, 0, sizeof(struct struct_multipleref));
-       len2 = marshal_unserialize(struct_multipleref, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_multipleref, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->f1, 15);
        ck_assert_int_eq(destination->f2, destination->f3);
@@ -365,15 +377,17 @@ START_TEST(test_circular_references) {
        };
 
        struct struct_circularref *destination;
+       void *p;
        void *buffer = NULL;
        size_t len, len2;
 
        len = marshal_serialize(struct_circularref, &source, &buffer);
        fail_unless(len > 0, "Unable to serialize");
        memset(&source, 0, sizeof(struct struct_circularref));
-       len2 = marshal_unserialize(struct_circularref, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_circularref, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->g1, 42);
        ck_assert_int_eq(destination->g2->g1, 42);
@@ -393,6 +407,7 @@ START_TEST(test_too_small_unmarshal) {
        };
 
        struct struct_nestedpointers *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
        int i, j;
@@ -407,14 +422,15 @@ START_TEST(test_too_small_unmarshal) {
        /* Loop 30 times to ease debugging leaks with valgrind */
        for (j = 0; j < 30; j++) {
                for (i = 0; i < len; i++) {
-                       len2 = marshal_unserialize(struct_nestedpointers, buffer, 1, &destination);
+                       len2 = marshal_unserialize(struct_nestedpointers, buffer, 1, &p);
                        fail_unless(len2 == 0,
                                    "Should not be able to deserialize, too small (%d<%d)",
                                    i, len);
                }
        }
-       len2 = marshal_unserialize(struct_nestedpointers, buffer, len + 5, &destination);
+       len2 = marshal_unserialize(struct_nestedpointers, buffer, len + 5, &p);
        fail_unless(len2 == len, "Deserialized too much");
+       destination = p;
        free(destination->c3);
        free(destination->c4); free(destination); free(buffer);
 
@@ -461,6 +477,7 @@ START_TEST(test_simple_list) {
                .g2 = &source_simple,
        };
        struct list_simple *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
        struct struct_simpleentry *e1, *e2;
@@ -479,10 +496,11 @@ START_TEST(test_simple_list) {
        memset(&entry2, 0, sizeof(struct struct_simpleentry));
        memset(&entry3, 0, sizeof(struct struct_simpleentry));
        memset(&entry4, 0, sizeof(struct struct_simpleentry));
-       len2 = marshal_unserialize(list_simple, buffer, len, &destination);
+       len2 = marshal_unserialize(list_simple, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
 
+       destination = p;
        e1 = TAILQ_FIRST(destination);
        ck_assert_int_eq(e1->g1, 47);
        s = e1->g2;
@@ -544,6 +562,7 @@ START_TEST(test_embedded_list) {
                .g2 = &source_simple,
        };
        struct struct_withlist *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
        struct struct_simpleentry *e1, *e2;
@@ -562,10 +581,11 @@ START_TEST(test_embedded_list) {
        memset(&entry2, 0, sizeof(struct struct_simpleentry));
        memset(&entry3, 0, sizeof(struct struct_simpleentry));
        memset(&entry4, 0, sizeof(struct struct_simpleentry));
-       len2 = marshal_unserialize(struct_withlist, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_withlist, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
 
+       destination = p;
        ck_assert_int_eq(destination->i1, 45424);
        ck_assert_int_eq(destination->i3, 4542);
        e1 = TAILQ_FIRST(&destination->i2);
@@ -609,15 +629,17 @@ START_TEST(test_string) {
                .s3 = "String 3",
        };
        struct struct_string *destination;
+       void *p;
        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);
+       len2 = marshal_unserialize(struct_string, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->s1, 44444);
        ck_assert_str_eq(destination->s2, "String 2");
@@ -646,15 +668,17 @@ START_TEST(test_fixed_string) {
                .s3 = "String 3",
        };
        struct struct_fixedstring *destination;
+       void *p;
        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_fixedstring));
-       len2 = marshal_unserialize(struct_fixedstring, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_fixedstring, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->s1, 44444);
        ck_assert_int_eq(destination->s2_len, 8);
@@ -687,15 +711,17 @@ START_TEST(test_ignore) {
                .t3 = 11111,
        };
        struct struct_ignore *destination;
+       void *p;
        void *buffer;
        size_t len, len2;
 
        len = marshal_serialize(struct_ignore, &source, &buffer);
        fail_unless(len > 0, "Unable to serialize");
        memset(&source, 0, sizeof(struct struct_ignore));
-       len2 = marshal_unserialize(struct_ignore, buffer, len, &destination);
+       len2 = marshal_unserialize(struct_ignore, buffer, len, &p);
        fail_unless(len2 > 0, "Unable to deserialize");
        free(buffer);
+       destination = p;
        ck_assert_int_eq(len, len2);
        ck_assert_int_eq(destination->t1, 4544);
        ck_assert_int_eq(destination->t2, NULL);