$ hg diff diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -51,6 +51,14 @@ whose size is determined when the object is allocated. */ +/* Used to make bytes and unicode hashes unpredictable. */ +#define Py_HASH_SEED_SUPPORTED /* TODO(gregory.p.smith): make this a configure +#ifdef Py_HASH_SEED_SUPPORTED +PyAPI_DATA(Py_hash_t) _Py_HashSeed; +#else +#define _Py_HashSeed 0 +#endif + /* Py_DEBUG implies Py_TRACE_REFS. */ #if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) #define Py_TRACE_REFS diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -8,6 +8,10 @@ extern "C" { #endif +#ifdef Py_HASH_SEED_SUPPORTED +Py_hash_t _Py_HashSeed; +#endif + #ifdef Py_REF_DEBUG Py_ssize_t _Py_RefTotal; @@ -759,7 +763,7 @@ Py_uhash_t x; Py_ssize_t i; - x = (Py_uhash_t) *p << 7; + x = _Py_HashSeed ^ ((Py_uhash_t) *p << 7); for (i = 0; i < len; i++) x = (1000003U * x) ^ (Py_uhash_t) *p++; x ^= (Py_uhash_t) len; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -11162,7 +11162,7 @@ /* The hash function as a macro, gets expanded three times below. */ #define HASH(P) \ - x = (Py_uhash_t)*P << 7; \ + x = _Py_HashSeed ^ ((Py_uhash_t)*P << 7); \ while (--len>= 0) \ x = (1000003*x) ^ (Py_uhash_t)*P++; diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -203,6 +203,12 @@ initialized = 1; _Py_Finalizing = NULL; +#ifdef Py_HASH_SEED_SUPPORTED + _Py_HashSeed = 0; /* TODO(gregory.p.smith): Init from a random source. */ + /* pid combined with highest resolution time possible at a minimum if + * a /dev/urandom or equivalent API is not available. */ +#endif + #if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE) /* Set up the LC_CTYPE locale, so we can obtain the locale's charset without having to switch