]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: use a struct member for 'inheritance' to avoid aliasing issues
authorOto Šťáva <oto.stava@nic.cz>
Wed, 15 Mar 2023 07:19:42 +0000 (08:19 +0100)
committerOto Šťáva <oto.stava@nic.cz>
Fri, 17 Mar 2023 07:18:43 +0000 (08:18 +0100)
It has been brought to my attention that using a macro to put an
identical member sequence at the beginning of multiple structs to
simulate OOP-like inheritance (the way libUV does it) may violate strict
aliasing rules. The standards-compliant way to do this should be to use
a single common struct member, as opposed to a common sequence of
members. This commit fixes this potential problem on our side.

Side note: even without this measure, it should not be causing any
problems for us, since we have '-fno-strict-aliasing' in our
meson.build. But in case libUV fixes their side at some point, let us
just have one less thing to worry about on our side.

daemon/http.c
daemon/io.c
daemon/session2.h
daemon/tls.c
daemon/worker.c

index aca3a9e0bdef2fc98d731da64c601b5ff4ff8938..8633c664fc474f0f1d2980938da61092b1c5af7b 100644 (file)
@@ -71,7 +71,7 @@ enum http_status {
 };
 
 struct pl_http_sess_data {
-       PROTOLAYER_DATA_HEADER();
+       struct protolayer_data h;
        struct nghttp2_session *h2;
 
        queue_http_stream streams;  /* Streams present in the wire buffer. */
@@ -389,7 +389,7 @@ static ssize_t send_callback(nghttp2_session *h2, const uint8_t *data, size_t le
        memcpy(send_ctx->data, data, length);
 
        kr_log_debug(DOH, "[%p] send_callback: %p\n", (void *)h2, (void *)send_ctx->data);
-       session2_wrap_after(http->session, PROTOLAYER_PROTOCOL_HTTP,
+       session2_wrap_after(http->h.session, PROTOLAYER_PROTOCOL_HTTP,
                        protolayer_buffer(send_ctx->data, length), NULL,
                        callback_finished_free_baton, send_ctx);
 
@@ -505,7 +505,7 @@ static int send_data_callback(nghttp2_session *h2, nghttp2_frame *frame, const u
                dest_iov[cur++] = (struct iovec){ (void *)padding, padlen - 1 };
 
        kr_assert(cur == iovcnt);
-       int ret = session2_wrap_after(http->session, PROTOLAYER_PROTOCOL_HTTP,
+       int ret = session2_wrap_after(http->h.session, PROTOLAYER_PROTOCOL_HTTP,
                        protolayer_iovec(dest_iov, cur),
                        NULL, callback_finished_free_baton, sdctx);
 
@@ -732,7 +732,7 @@ static int submit_to_wirebuffer(struct pl_http_sess_data *ctx)
        }
 
        ret = 0;
-       session2_unwrap_after(ctx->session, PROTOLAYER_PROTOCOL_HTTP,
+       session2_unwrap_after(ctx->h.session, PROTOLAYER_PROTOCOL_HTTP,
                        protolayer_wire_buf(wb), NULL, NULL, NULL);
 cleanup:
        http_cleanup_stream(ctx);
index 1014c046d8865aafb9629ae46d615542b9e4bd7c..4f61a0a9c86318984d2a8e683040fdec26d4b606 100644 (file)
@@ -130,7 +130,7 @@ static int family_to_freebind_option(sa_family_t sa_family, int *level, int *nam
 
 
 struct pl_udp_iter_data {
-       PROTOLAYER_DATA_HEADER();
+       struct protolayer_data h;
        struct proxy_result proxy;
        bool has_proxy;
 };
@@ -212,7 +212,7 @@ static enum protolayer_event_cb_result pl_udp_event_wrap(
 
 
 struct pl_tcp_sess_data {
-       PROTOLAYER_DATA_HEADER();
+       struct protolayer_data h;
        struct proxy_result proxy;
        struct wire_buf wire_buf;
        bool had_data : 1;
index a0d6701f5c0684ef9bd33b3f9ddbd67eb979576d..401d5c58cc9bc67088b1ef60db55a9c696d1c137 100644 (file)
@@ -499,14 +499,10 @@ size_t protolayer_queue_count_payload(const protolayer_iter_ctx_queue_t *queue);
  * queue iterators, as it does not need to iterate through the whole queue. */
 bool protolayer_queue_has_payload(const protolayer_iter_ctx_queue_t *queue);
 
-/** Mandatory header members for any layer-specific data. */
-#define PROTOLAYER_DATA_HEADER() struct {\
-       struct session2 *session; /**< Pointer to the owner session. */\
-}
-
-/** Layer-specific data - the generic struct. */
+/** Layer-specific data - the generic struct. To be added as the first member of
+ * each specific struct. */
 struct protolayer_data {
-       PROTOLAYER_DATA_HEADER();
+       struct session2 *session; /**< Pointer to the owner session. */\
 };
 
 /** Return value of `protolayer_iter_cb` callbacks. To be returned by *layer
@@ -654,7 +650,7 @@ struct protolayer_data_param {
 struct protolayer_globals {
        /** Size of the layer-specific data struct, valid per-session.
         *
-        * The struct MUST begin with the `PROTOLAYER_DATA_HEADER()` macro. If
+        * The struct MUST begin with a `struct protolayer_data` member. If
         * no session struct is used by the layer, the value may be zero. */
        size_t sess_size;
 
@@ -662,7 +658,7 @@ struct protolayer_globals {
         * gets created and destroyed together with a `struct
         * protolayer_iter_ctx`.
         *
-        * The struct MUST begin with the `PROTOLAYER_DATA_HEADER()` macro. If
+        * The struct MUST begin with a `struct protolayer_data` member. If
         * no iteration struct is used by the layer, the value may be zero. */
        size_t iter_size;
 
index 73a31b06947f633f1f6530218a8e6d15a26f3132..63f0e3fe052abdee228b37b2a80be6beabc5d00c 100644 (file)
@@ -49,7 +49,7 @@ typedef enum tls_client_hs_state {
 } tls_hs_state_t;
 
 struct pl_tls_sess_data {
-       PROTOLAYER_DATA_HEADER();
+       struct protolayer_data h;
        bool client_side;
        bool first_handshake_done;
        gnutls_session_t tls_session;
@@ -226,7 +226,7 @@ static ssize_t kres_gnutls_vec_push(gnutls_transport_ptr_t h, const giovec_t * i
        push_ctx->sess_data = tls;
        memcpy(push_ctx->iov, iov, sizeof(struct iovec[iovcnt]));
 
-       session2_wrap_after(tls->session, PROTOLAYER_PROTOCOL_TLS,
+       session2_wrap_after(tls->h.session, PROTOLAYER_PROTOCOL_TLS,
                        protolayer_iovec(push_ctx->iov, iovcnt), NULL,
                        kres_gnutls_push_finished, push_ctx);
 
index 3805638df687c292d2dad96d2ddda26d65726257..996eb9beb4c006d1d800472ca0471e04208ee848 100644 (file)
@@ -1800,13 +1800,13 @@ static enum protolayer_iter_cb_result pl_dns_dgram_unwrap(
 }
 
 struct pl_dns_stream_sess_data {
-       PROTOLAYER_DATA_HEADER();
+       struct protolayer_data h;
        bool single : 1; /**< True: Stream only allows a single packet */
        bool produced : 1; /**< True: At least one packet has been produced */
 };
 
 struct pl_dns_stream_iter_data {
-       PROTOLAYER_DATA_HEADER();
+       struct protolayer_data h;
        struct {
                knot_mm_t *pool;
                void *mem;