From 3e7de27c00bb9ea46a3ef3efdae957012290d7ff Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sat, 3 Apr 2021 23:15:12 +0200 Subject: [PATCH] Rename M_HASH_SEED into M_USE_HASH_SEED as it a user overridable macro (API break). --- README.md | 23 ++++++++++++++++++----- doc/API.txt | 1 + example/ex-multi03.c | 2 +- m-core.h | 14 +++++++------- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a74ab2f2..393e736d 100644 --- a/README.md +++ b/README.md @@ -5950,12 +5950,19 @@ the string is truncated. Example: #### HASH Functions -##### M\_HASH\_SEED --> size\_t +##### M\_USE\_HASH\_SEED -User shall overwrite this macro by a random seed (of type size\_t) before including -the header m-core.h that hash functions use this variable -as the seed for their hash computation. -If no user macro is defined, the default is to use 0, +A User modifiable macro defining the initial random seed (of type size\_t). +It shall be define before including any header of M\*LIB, +so that hash functions use this variable +as their initial seed for their hash computation of an object. +It can be used to generate less predictable hash values at runtime, +which may protect against +[DOS dictionary attacks](https://events.ccc.de/congress/2011/Fahrplan/attachments/2007_28C3_Effective_DoS_on_web_application_platforms.pdf). +It shall be unique for a running instance of M\*LIB. +Note that using a random seed is not enough to protect efficienly againt +such attacks. A cryptographic secure hash may be also needed. +If it is not defined, the default is to use the value 0, making all hash computations predictable. ##### M\_HASH\_DECL(hash) @@ -7686,6 +7693,12 @@ Define the default size of a segment for a deque structure. Default value: 8 elements. +### M\_USE\_HASH\_SEED + +Define the seed to inject to the hash computation of an object. + +Default value: 0 (predictable hash) + ### M\_MEMORY\_ALLOC See [m-core.h](#m-core) diff --git a/doc/API.txt b/doc/API.txt index dd8cdfaa..cab0b797 100644 --- a/doc/API.txt +++ b/doc/API.txt @@ -63,4 +63,5 @@ V0.5.*: * M_INVERT is renamed into M_REVERSE to be more coherent with the REVERS * Remove ALGO_INIT_VA & M_ALG0_LET_INIT_VAI of m-algo as it has been deprecated. Use of M_LET instead. * Some Internal name of user modifiable macros have been renamed to be properly customizable by the user. + * Rename M_HASH_SEED into M_USE_HASH_SEED as it is a user macro. \ No newline at end of file diff --git a/example/ex-multi03.c b/example/ex-multi03.c index 89ede154..67c514f9 100644 --- a/example/ex-multi03.c +++ b/example/ex-multi03.c @@ -4,7 +4,7 @@ /* Register a dynamic seed to M*LIB hash function. This shall be done before any M*LIB header inclusion. */ unsigned long long rand_seed; -#define M_HASH_SEED rand_seed +#define M_USE_HASH_SEED rand_seed #include "m-array.h" #include "m-dict.h" diff --git a/m-core.h b/m-core.h index 4040ad40..dfbe5412 100644 --- a/m-core.h +++ b/m-core.h @@ -2293,8 +2293,8 @@ m_core_snprintf(char *str, size_t size, const char *format, ...) so that the hash are not easily predictible by an attacker. See https://events.ccc.de/congress/2011/Fahrplan/attachments/2007_28C3_Effective_DoS_on_web_application_platforms.pdf */ -#ifndef M_HASH_SEED -# define M_HASH_SEED 0UL +#ifndef M_USE_HASH_SEED +# define M_USE_HASH_SEED 0UL #endif #if defined(M_USE_DJB_HASH) @@ -2324,7 +2324,7 @@ m_core_snprintf(char *str, size_t size, const char *format, ...) #define M_HASH_CALC(h1,h2) (((h1) * 0x811C9DC5UL) ^ (h2)) #endif -#define M_HASH_DECL(hash) size_t hash = M_HASH_INIT ^ M_HASH_SEED +#define M_HASH_DECL(hash) size_t hash = M_HASH_INIT ^ M_USE_HASH_SEED #define M_HASH_UP(hash,h) do { hash = (size_t) M_HASH_CALC(hash, (h)); } while (0) #define M_HASH_FINAL(hash) ( (hash) >> (sizeof(size_t)*CHAR_BIT/2) | (hash) ) @@ -2454,7 +2454,7 @@ static inline uint32_t m_core_hash (const void *str, size_t length) { const uint32_t prime = 709607U; - uint32_t hash32 = 2166136261U ^ M_HASH_SEED; + uint32_t hash32 = 2166136261U ^ M_USE_HASH_SEED; const uint8_t *p = (const uint8_t *)str; M_ASSERT (str != NULL || length == 0); @@ -2487,7 +2487,7 @@ static inline uint64_t m_core_hash (const void *str, size_t length) { const uint64_t prime = 1099511628211ULL; - uint64_t hash64 = 14695981039346656037ULL ^ M_HASH_SEED; + uint64_t hash64 = 14695981039346656037ULL ^ M_USE_HASH_SEED; const uint8_t *p = M_ASSIGN_CAST(const uint8_t *, str); M_ASSERT (str != NULL || length == 0); @@ -2540,8 +2540,8 @@ static inline size_t m_core_cstr_hash(const char str[]) NOTE: Default case is not safe if the type is defined with the '[1]' trick. */ #define M_HASH_POD_DEFAULT(a) m_core_hash((const void*) &(a), sizeof (a)) #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L -#define M_HASH_INT32(a) ( (a) ^ ((a) << 11) ^ M_HASH_SEED ) -#define M_HASH_INT64(a) ( ( (a) >> 33 ) ^ (a) ^ ((a) << 11) ^ M_HASH_SEED ) +#define M_HASH_INT32(a) ( (a) ^ ((a) << 11) ^ M_USE_HASH_SEED ) +#define M_HASH_INT64(a) ( ( (a) >> 33 ) ^ (a) ^ ((a) << 11) ^ M_USE_HASH_SEED ) #define M_HASH_DEFAULT(a) \ (size_t) _Generic((a)+0, \ int32_t: M_HASH_INT32((uint32_t) M_AS_TYPE(int32_t, a)), \