Skip to content

Commit e6904da

Browse files
Fix strict aliasing UB in MurMur hash implementation.
This was spotted when trying to upgrade the libseccomp fedora package to version 2.6.0 in fedora rawhide. It comes with gcc 15 and LTO enabled by default. When running the test 61-sim-transactions we get plenty of such errors in valgrind: ==265507== Use of uninitialised value of size 8 ==265507== at 0x4096AD: _hsh_add (gen_bpf.c:599) ==265507== by 0x40A557: UnknownInlinedFun (gen_bpf.c:2016) ==265507== by 0x40A557: gen_bpf_generate (gen_bpf.c:2341) ==265507== by 0x400CDE: UnknownInlinedFun (db.c:2685) ==265507== by 0x400CDE: UnknownInlinedFun (db.c:2682) ==265507== by 0x400CDE: UnknownInlinedFun (api.c:756) ==265507== by 0x400CDE: UnknownInlinedFun (util.c:162) ==265507== by 0x400CDE: UnknownInlinedFun (util.c:153) ==265507== by 0x400CDE: main (61-sim-transactions.c:128) ==265507== Uninitialised value was created by a stack allocation ==265507== at 0x409590: _hsh_add (gen_bpf.c:573) Investigating this a bit, it seems that because of LTO the MurMur hash implementation is being inlined in _hsh_add. The way we call getblock32 with the explicit cast to const uint32_t* is a strict aliasing violation. This is reproducible on a "fedora:rawhide" container (gcc 15) and using: export CFLAGS='-O2 -flto=auto -ffat-lto-objects -g' Signed-off-by: Romain Geissler <[email protected]>
1 parent 7db46d7 commit e6904da

File tree

1 file changed

+2
-6
lines changed

1 file changed

+2
-6
lines changed

src/hash.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,11 @@
1212
*/
1313

1414
#include <stdlib.h>
15+
#include <string.h>
1516
#include <inttypes.h>
1617

1718
#include "hash.h"
1819

19-
static inline uint32_t getblock32(const uint32_t *p, int i)
20-
{
21-
return p[i];
22-
}
23-
2420
static inline uint32_t rotl32(uint32_t x, int8_t r)
2521
{
2622
return (x << r) | (x >> (32 - r));
@@ -56,7 +52,7 @@ uint32_t hash(const void *key, size_t length)
5652
/* body */
5753
blocks = (const uint32_t *)(data + nblocks * 4);
5854
for(i = -nblocks; i; i++) {
59-
k1 = getblock32(blocks, i);
55+
memcpy(&k1, &blocks[i], sizeof(uint32_t));
6056

6157
k1 *= c1;
6258
k1 = rotl32(k1, 15);

0 commit comments

Comments
 (0)