.. cmdoption:: -R
- Kept for compatibility. On Python 3.3 and greater, hash randomization is
- turned on by default.
+ Turn on hash randomization. This option only has an effect if the
+ :envvar:`PYTHONHASHSEED` environment variable is set to ``0``, since hash
+ randomization is enabled by default.
On previous versions of Python, this option turns on hash randomization,
so that the :meth:`__hash__` values of str, bytes and datetime
PyAPI_FUNC(int) _PyFrame_Init(void);
PyAPI_FUNC(int) _PyFloat_Init(void);
PyAPI_FUNC(int) PyByteArray_Init(void);
-PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(_PyCoreConfig *core_config);
+PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(const _PyCoreConfig *);
+#endif
+#ifdef Py_BUILD_CORE
+PyAPI_FUNC(int) _Py_ReadHashSeed(
+ const char *seed_text,
+ int *use_hash_seed,
+ unsigned long *hash_seed);
#endif
/* Various internal finalizers */
# Verify that sys.flags contains hash_randomization
code = 'import sys; print("random is", sys.flags.hash_randomization)'
- rc, out, err = assert_python_ok('-c', code)
- self.assertEqual(rc, 0)
+ rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='')
+ self.assertIn(b'random is 1', out)
+
+ rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='random')
+ self.assertIn(b'random is 1', out)
+
+ rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='0')
+ self.assertIn(b'random is 0', out)
+
+ rc, out, err = assert_python_ok('-R', '-c', code, PYTHONHASHSEED='0')
self.assertIn(b'random is 1', out)
def test_del___main__(self):
--- /dev/null
+The :option:`-R` option now turns on hash randomization when the
+:envvar:`PYTHONHASHSEED` environment variable is set to ``0``. Previously,
+the option was ignored. Moreover, ``sys.flags.hash_randomization`` is now
+properly set to 0 when hash randomization is turned off by
+``PYTHONHASHSEED=0``.
break;
case 'R':
- /* Ignored */
+ pymain->core_config.use_hash_seed = 0;
break;
/* This space reserved for other options */
Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment;
Py_UTF8Mode = pymain->core_config.utf8_mode;
+
+ /* Random or non-zero hash seed */
+ Py_HashRandomizationFlag = (pymain->core_config.use_hash_seed == 0 ||
+ pymain->core_config.hash_seed != 0);
}
}
+static _PyInitError
+config_init_hash_seed(_PyCoreConfig *config)
+{
+ if (config->use_hash_seed < 0) {
+ const char *seed_text = pymain_get_env_var("PYTHONHASHSEED");
+ int use_hash_seed;
+ unsigned long hash_seed;
+ if (_Py_ReadHashSeed(seed_text, &use_hash_seed, &hash_seed) < 0) {
+ return _Py_INIT_USER_ERR("PYTHONHASHSEED must be \"random\" "
+ "or an integer in range [0; 4294967295]");
+ }
+ config->use_hash_seed = use_hash_seed;
+ config->hash_seed = hash_seed;
+ }
+ return _Py_INIT_OK();
+}
+
+
_PyInitError
_PyCoreConfig_ReadEnv(_PyCoreConfig *config)
{
return err;
}
+ err = config_init_hash_seed(config);
+ if (_Py_INIT_FAILED(err)) {
+ return err;
+ }
+
return _Py_INIT_OK();
}
/* Get environment variables */
pymain_set_flags_from_env(pymain);
- /* The variable is only tested for existence here;
- _Py_HashRandomization_Init will check its value further. */
- if (pymain_get_env_var("PYTHONHASHSEED")) {
- Py_HashRandomizationFlag = 1;
- }
-
if (pymain_warnings_envvar(pymain) < 0) {
return -1;
}
return pyurandom(buffer, size, 0, 1);
}
-int Py_ReadHashSeed(const char *seed_text,
- int *use_hash_seed,
- unsigned long *hash_seed)
+int
+_Py_ReadHashSeed(const char *seed_text,
+ int *use_hash_seed,
+ unsigned long *hash_seed)
{
Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
/* Convert a text seed to a numeric one */
return 0;
}
-static _PyInitError
-init_hash_secret(int use_hash_seed,
- unsigned long hash_seed)
+
+_PyInitError
+_Py_HashRandomization_Init(const _PyCoreConfig *config)
{
void *secret = &_Py_HashSecret;
Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
}
_Py_HashSecret_Initialized = 1;
- if (use_hash_seed) {
- if (hash_seed == 0) {
+ if (config->use_hash_seed) {
+ if (config->hash_seed == 0) {
/* disable the randomized hash */
memset(secret, 0, secret_size);
}
else {
/* use the specified hash seed */
- lcg_urandom(hash_seed, secret, secret_size);
+ lcg_urandom(config->hash_seed, secret, secret_size);
}
}
else {
return _Py_INIT_OK();
}
-_PyInitError
-_Py_HashRandomization_Init(_PyCoreConfig *core_config)
-{
- const char *seed_text;
- int use_hash_seed = core_config->use_hash_seed;
- unsigned long hash_seed = core_config->hash_seed;
-
- if (use_hash_seed < 0) {
- seed_text = Py_GETENV("PYTHONHASHSEED");
- if (Py_ReadHashSeed(seed_text, &use_hash_seed, &hash_seed) < 0) {
- return _Py_INIT_USER_ERR("PYTHONHASHSEED must be \"random\" "
- "or an integer in range [0; 4294967295]");
- }
- core_config->use_hash_seed = use_hash_seed;
- core_config->hash_seed = hash_seed;
- }
- return init_hash_secret(use_hash_seed, hash_seed);
-}
void
_Py_HashRandomization_Fini(void)