Unverified Kaydet (Commit) 358e5e17 authored tarafından Victor Stinner's avatar Victor Stinner Kaydeden (comit) GitHub

bpo-32329: Fix -R option for hash randomization (#4873)

bpo-32329, bpo-32030:

* The -R option now turns on hash randomization when the
  PYTHONHASHSEED environment variable is set to 0 Previously, the
  option was ignored.
* sys.flags.hash_randomization is now properly set to 0 when hash
  randomization is turned off by PYTHONHASHSEED=0.
* _PyCoreConfig_ReadEnv() now reads the PYTHONHASHSEED environment
  variable. _Py_HashRandomization_Init() now only apply the
  configuration, it doesn't read PYTHONHASHSEED anymore.
üst 96a5e50a
...@@ -277,8 +277,9 @@ Miscellaneous options ...@@ -277,8 +277,9 @@ Miscellaneous options
.. cmdoption:: -R .. cmdoption:: -R
Kept for compatibility. On Python 3.3 and greater, hash randomization is Turn on hash randomization. This option only has an effect if the
turned on by default. :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, On previous versions of Python, this option turns on hash randomization,
so that the :meth:`__hash__` values of str, bytes and datetime so that the :meth:`__hash__` values of str, bytes and datetime
......
...@@ -136,7 +136,13 @@ PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void); ...@@ -136,7 +136,13 @@ PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void);
PyAPI_FUNC(int) _PyFrame_Init(void); PyAPI_FUNC(int) _PyFrame_Init(void);
PyAPI_FUNC(int) _PyFloat_Init(void); PyAPI_FUNC(int) _PyFloat_Init(void);
PyAPI_FUNC(int) PyByteArray_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 #endif
/* Various internal finalizers */ /* Various internal finalizers */
......
...@@ -432,8 +432,16 @@ class CmdLineTest(unittest.TestCase): ...@@ -432,8 +432,16 @@ class CmdLineTest(unittest.TestCase):
# Verify that sys.flags contains hash_randomization # Verify that sys.flags contains hash_randomization
code = 'import sys; print("random is", sys.flags.hash_randomization)' code = 'import sys; print("random is", sys.flags.hash_randomization)'
rc, out, err = assert_python_ok('-c', code) rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='')
self.assertEqual(rc, 0) 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) self.assertIn(b'random is 1', out)
def test_del___main__(self): def test_del___main__(self):
......
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``.
...@@ -726,7 +726,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain) ...@@ -726,7 +726,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain)
break; break;
case 'R': case 'R':
/* Ignored */ pymain->core_config.use_hash_seed = 0;
break; break;
/* This space reserved for other options */ /* This space reserved for other options */
...@@ -1293,6 +1293,10 @@ pymain_set_global_config(_PyMain *pymain) ...@@ -1293,6 +1293,10 @@ pymain_set_global_config(_PyMain *pymain)
Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment;
Py_UTF8Mode = pymain->core_config.utf8_mode; 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);
} }
...@@ -1694,6 +1698,24 @@ config_init_home(_PyCoreConfig *config) ...@@ -1694,6 +1698,24 @@ config_init_home(_PyCoreConfig *config)
} }
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 _PyInitError
_PyCoreConfig_ReadEnv(_PyCoreConfig *config) _PyCoreConfig_ReadEnv(_PyCoreConfig *config)
{ {
...@@ -1712,6 +1734,11 @@ _PyCoreConfig_ReadEnv(_PyCoreConfig *config) ...@@ -1712,6 +1734,11 @@ _PyCoreConfig_ReadEnv(_PyCoreConfig *config)
return err; return err;
} }
err = config_init_hash_seed(config);
if (_Py_INIT_FAILED(err)) {
return err;
}
return _Py_INIT_OK(); return _Py_INIT_OK();
} }
...@@ -1777,12 +1804,6 @@ pymain_parse_envvars(_PyMain *pymain) ...@@ -1777,12 +1804,6 @@ pymain_parse_envvars(_PyMain *pymain)
/* Get environment variables */ /* Get environment variables */
pymain_set_flags_from_env(pymain); 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) { if (pymain_warnings_envvar(pymain) < 0) {
return -1; return -1;
} }
......
...@@ -533,7 +533,8 @@ _PyOS_URandomNonblock(void *buffer, Py_ssize_t size) ...@@ -533,7 +533,8 @@ _PyOS_URandomNonblock(void *buffer, Py_ssize_t size)
return pyurandom(buffer, size, 0, 1); return pyurandom(buffer, size, 0, 1);
} }
int Py_ReadHashSeed(const char *seed_text, int
_Py_ReadHashSeed(const char *seed_text,
int *use_hash_seed, int *use_hash_seed,
unsigned long *hash_seed) unsigned long *hash_seed)
{ {
...@@ -561,9 +562,9 @@ int Py_ReadHashSeed(const char *seed_text, ...@@ -561,9 +562,9 @@ int Py_ReadHashSeed(const char *seed_text,
return 0; return 0;
} }
static _PyInitError
init_hash_secret(int use_hash_seed, _PyInitError
unsigned long hash_seed) _Py_HashRandomization_Init(const _PyCoreConfig *config)
{ {
void *secret = &_Py_HashSecret; void *secret = &_Py_HashSecret;
Py_ssize_t secret_size = sizeof(_Py_HashSecret_t); Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
...@@ -573,14 +574,14 @@ init_hash_secret(int use_hash_seed, ...@@ -573,14 +574,14 @@ init_hash_secret(int use_hash_seed,
} }
_Py_HashSecret_Initialized = 1; _Py_HashSecret_Initialized = 1;
if (use_hash_seed) { if (config->use_hash_seed) {
if (hash_seed == 0) { if (config->hash_seed == 0) {
/* disable the randomized hash */ /* disable the randomized hash */
memset(secret, 0, secret_size); memset(secret, 0, secret_size);
} }
else { else {
/* use the specified hash seed */ /* use the specified hash seed */
lcg_urandom(hash_seed, secret, secret_size); lcg_urandom(config->hash_seed, secret, secret_size);
} }
} }
else { else {
...@@ -601,24 +602,6 @@ init_hash_secret(int use_hash_seed, ...@@ -601,24 +602,6 @@ init_hash_secret(int use_hash_seed,
return _Py_INIT_OK(); 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 void
_Py_HashRandomization_Fini(void) _Py_HashRandomization_Fini(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment