From 8b5075806d551a7a20693b5edb76a6e8d2fe1816 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 25 Feb 2020 09:35:07 +0100 Subject: [PATCH] CLEANUP: cache: use read_u32/write_u32 to access the cache entry's hash Enabling strict aliasing fails on the cache's hash which is a series of 20 bytes cast as u32. And in practice it could even fail on some archs if the http_txn didn't guarantee the hash was properly aligned. Let's use read_u32() to read the value and write_u32() to set it, this makes sure the compiler emits the correct code to access these and knows about the intentional aliasing. --- src/cache.c | 7 ++++--- src/http_ana.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cache.c b/src/cache.c index dc11cf532..b0be2094d 100644 --- a/src/cache.c +++ b/src/cache.c @@ -36,6 +36,7 @@ #include #include #include +#include #define CACHE_FLT_F_IMPLICIT_DECL 0x00000001 /* The cache filtre was implicitly declared (ie without * the filter keyword) */ @@ -95,7 +96,7 @@ struct cache_entry *entry_exist(struct cache *cache, char *hash) struct eb32_node *node; struct cache_entry *entry; - node = eb32_lookup(&cache->entries, (*(unsigned int *)hash)); + node = eb32_lookup(&cache->entries, read_u32(hash)); if (!node) return NULL; @@ -549,7 +550,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px, struct shared_context *shctx = shctx_ptr(cconf->c.cache); struct cache_st *cache_ctx = NULL; struct cache_entry *object, *old; - unsigned int key = *(unsigned int *)txn->cache_hash; + unsigned int key = read_u32(txn->cache_hash); struct htx *htx; struct http_hdr_ctx ctx; size_t hdrs_len = 0; @@ -1530,7 +1531,7 @@ static int cli_io_handler_show_cache(struct appctx *appctx) } entry = container_of(node, struct cache_entry, eb); - chunk_printf(&trash, "%p hash:%u size:%u (%u blocks), refcount:%u, expire:%d\n", entry, (*(unsigned int *)entry->hash), block_ptr(entry)->len, block_ptr(entry)->block_count, block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec); + chunk_printf(&trash, "%p hash:%u size:%u (%u blocks), refcount:%u, expire:%d\n", entry, read_u32(entry->hash), block_ptr(entry)->len, block_ptr(entry)->block_count, block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec); next_key = node->key + 1; appctx->ctx.cli.i0 = next_key; diff --git a/src/http_ana.c b/src/http_ana.c index b55e1bc77..e3d22445e 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -5047,7 +5048,7 @@ void http_init_txn(struct stream *s) : 0); txn->status = -1; txn->errmsg = NULL; - *(unsigned int *)txn->cache_hash = 0; + write_u32(txn->cache_hash, 0); txn->cookie_first_date = 0; txn->cookie_last_date = 0;