ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
uthash.h
Go to the documentation of this file.
1
23#pragma once
24
25// NOTE: This wrapper provides UBSan-safe hash functions for uthash
26// Files should include common.h BEFORE including any uthash-using headers
27
28// Only define custom allocators if SAFE_MALLOC is available
29// This allows headers to include uthash before common.h is fully processed
30#ifdef SAFE_MALLOC
31#define uthash_malloc(sz) SAFE_MALLOC(sz, void *)
32#define uthash_free(ptr, sz) SAFE_FREE(ptr)
33#endif
34
35// Include fnv1a for hash function (it doesn't depend on common.h)
36#include "util/fnv1a.h"
37
38// UBSan-safe hash wrapper for uthash (fnv1a uses 64-bit arithmetic, no overflow)
39// Note: uthash expects HASH_FUNCTION(keyptr, keylen, hashv) where hashv is an output parameter
40#undef HASH_FUNCTION
41#define HASH_FUNCTION(keyptr, keylen, hashv) \
42 do { \
43 if (!(keyptr) || (keylen) == 0) { \
44 (hashv) = 1; /* Non-zero constant for safety */ \
45 } else { \
46 (hashv) = fnv1a_hash_bytes((keyptr), (keylen)); \
47 } \
48 } while (0)
49
50// Include the upstream uthash header
51#include <ascii-chat-deps/uthash/src/uthash.h>
52
53// Redefine HASH_JEN_MIX to use safe arithmetic that doesn't trigger UBSan
54// This prevents undefined behavior from left shifts that exceed uint32_t range
55// The original uthash uses shifts that can overflow, but we fix it by using
56// 64-bit arithmetic for intermediate calculations, then casting back to 32-bit
57// Must be defined AFTER including uthash.h since uthash.h unconditionally defines it
58#undef HASH_JEN_MIX
59#define HASH_JEN_MIX(a, b, c) \
60 do { \
61 /* Use 64-bit arithmetic for shifts to avoid undefined behavior, then mask back to 32-bit */ \
62 uint64_t _a = (uint64_t)(a), _b = (uint64_t)(b), _c = (uint64_t)(c); \
63 _a -= _b; \
64 _a -= _c; \
65 _a ^= (_c >> 13); \
66 a = (unsigned)(_a & 0xFFFFFFFFU); \
67 \
68 _b -= _c; \
69 _b -= (uint64_t)a; \
70 _b ^= (((uint64_t)a << 8) & 0xFFFFFFFFU); \
71 b = (unsigned)(_b & 0xFFFFFFFFU); \
72 \
73 _c -= (uint64_t)a; \
74 _c -= (uint64_t)b; \
75 _c ^= ((uint64_t)b >> 13); \
76 c = (unsigned)(_c & 0xFFFFFFFFU); \
77 \
78 _a = (uint64_t)a; \
79 _a -= (uint64_t)b; \
80 _a -= (uint64_t)c; \
81 _a ^= ((uint64_t)c >> 12); \
82 a = (unsigned)(_a & 0xFFFFFFFFU); \
83 \
84 _b = (uint64_t)b; \
85 _b -= (uint64_t)c; \
86 _b -= (uint64_t)a; \
87 _b ^= (((uint64_t)a << 16) & 0xFFFFFFFFU); \
88 b = (unsigned)(_b & 0xFFFFFFFFU); \
89 \
90 _c = (uint64_t)c; \
91 _c -= (uint64_t)a; \
92 _c -= (uint64_t)b; \
93 _c ^= ((uint64_t)b >> 5); \
94 c = (unsigned)(_c & 0xFFFFFFFFU); \
95 \
96 _a = (uint64_t)a; \
97 _a -= (uint64_t)b; \
98 _a -= (uint64_t)c; \
99 _a ^= ((uint64_t)c >> 3); \
100 a = (unsigned)(_a & 0xFFFFFFFFU); \
101 \
102 _b = (uint64_t)b; \
103 _b -= (uint64_t)c; \
104 _b -= (uint64_t)a; \
105 _b ^= (((uint64_t)a << 10) & 0xFFFFFFFFU); \
106 b = (unsigned)(_b & 0xFFFFFFFFU); \
107 \
108 _c = (uint64_t)c; \
109 _c -= (uint64_t)a; \
110 _c -= (uint64_t)b; \
111 _c ^= ((uint64_t)b >> 15); \
112 c = (unsigned)(_c & 0xFFFFFFFFU); \
113 } while (0)
#️⃣ FNV-1a Hash Function Implementation