From: Vincent Bernat Date: Sun, 23 Dec 2012 12:08:26 +0000 (+0100) Subject: marshal: respect GCC strict-aliasing rule X-Git-Tag: 0.7.0~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0e940d8ddac56f6cae7a4aa7d41c1b8cd724bb88;p=thirdparty%2Flldpd.git marshal: respect GCC strict-aliasing rule 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. --- diff --git a/src/daemon/client.c b/src/daemon/client.c index e48216e4..87059e62 100644 --- a/src/daemon/client.c +++ b/src/daemon/client.c @@ -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; diff --git a/src/lib/atom.c b/src/lib/atom.c index 2e3586b3..1486b1fa 100644 --- a/src/lib/atom.c +++ b/src/lib/atom.c @@ -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; } diff --git a/src/lib/connection.c b/src/lib/connection.c index 1aa3d370..405cce18 100644 --- a/src/lib/connection.c +++ b/src/lib/connection.c @@ -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) { diff --git a/src/marshal.h b/src/marshal.h index 4f6da2ac..eed7c9f2 100644 --- a/src/marshal.h +++ b/src/marshal.h @@ -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 diff --git a/tests/check_marshal.c b/tests/check_marshal.c index f6d14dd8..3dd4f649 100644 --- a/tests/check_marshal.c +++ b/tests/check_marshal.c @@ -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);