$ 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