mirror of
https://github.com/python/cpython.git
synced 2025-07-23 19:25:40 +00:00
enable hash randomization by default
This commit is contained in:
parent
6ca5a4d49f
commit
c9f54cf512
9 changed files with 44 additions and 65 deletions
|
@ -1277,7 +1277,29 @@ Basic customization
|
||||||
inheritance of :meth:`__hash__` will be blocked, just as if :attr:`__hash__`
|
inheritance of :meth:`__hash__` will be blocked, just as if :attr:`__hash__`
|
||||||
had been explicitly set to :const:`None`.
|
had been explicitly set to :const:`None`.
|
||||||
|
|
||||||
See also the :option:`-R` command-line option.
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Note by default the :meth:`__hash__` values of str, bytes and datetime
|
||||||
|
objects are "salted" with an unpredictable random value. Although they
|
||||||
|
remain constant within an individual Python process, they are not
|
||||||
|
predictable between repeated invocations of Python.
|
||||||
|
|
||||||
|
This is intended to provide protection against a denial-of-service caused
|
||||||
|
by carefully-chosen inputs that exploit the worst case performance of a
|
||||||
|
dict insertion, O(n^2) complexity. See
|
||||||
|
http://www.ocert.org/advisories/ocert-2011-003.html for details.
|
||||||
|
|
||||||
|
Changing hash values affects the order in which keys are retrieved from a
|
||||||
|
dict. Although Python has never made guarantees about this ordering (and
|
||||||
|
it typically varies between 32-bit and 64-bit builds), enough real-world
|
||||||
|
code implicitly relies on this non-guaranteed behavior that the
|
||||||
|
randomization is disabled by default.
|
||||||
|
|
||||||
|
See also :envvar:`PYTHONHASHSEED`.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.3
|
||||||
|
Hash randomization is enabled by default.
|
||||||
|
|
||||||
|
|
||||||
.. method:: object.__bool__(self)
|
.. method:: object.__bool__(self)
|
||||||
|
|
|
@ -24,7 +24,7 @@ Command line
|
||||||
|
|
||||||
When invoking Python, you may specify any of these options::
|
When invoking Python, you may specify any of these options::
|
||||||
|
|
||||||
python [-bBdEhiORqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
|
python [-bBdEhiOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
|
||||||
|
|
||||||
The most common use case is, of course, a simple invocation of a script::
|
The most common use case is, of course, a simple invocation of a script::
|
||||||
|
|
||||||
|
@ -486,9 +486,8 @@ These environment variables influence Python's behavior.
|
||||||
|
|
||||||
.. envvar:: PYTHONHASHSEED
|
.. envvar:: PYTHONHASHSEED
|
||||||
|
|
||||||
If this variable is set to ``random``, the effect is the same as specifying
|
If this variable is set to ``random``, a random value is used to seed the
|
||||||
the :option:`-R` option: a random value is used to seed the hashes of str,
|
hashes of str, bytes and datetime objects.
|
||||||
bytes and datetime objects.
|
|
||||||
|
|
||||||
If :envvar:`PYTHONHASHSEED` is set to an integer value, it is used as a fixed
|
If :envvar:`PYTHONHASHSEED` is set to an integer value, it is used as a fixed
|
||||||
seed for generating the hash() of the types covered by the hash
|
seed for generating the hash() of the types covered by the hash
|
||||||
|
@ -499,8 +498,7 @@ These environment variables influence Python's behavior.
|
||||||
values.
|
values.
|
||||||
|
|
||||||
The integer must be a decimal number in the range [0,4294967295]. Specifying
|
The integer must be a decimal number in the range [0,4294967295]. Specifying
|
||||||
the value 0 will lead to the same hash values as when hash randomization is
|
the value 0 will disable hash randomization.
|
||||||
disabled.
|
|
||||||
|
|
||||||
.. versionadded:: 3.2.3
|
.. versionadded:: 3.2.3
|
||||||
|
|
||||||
|
|
|
@ -330,14 +330,14 @@ class CmdLineTest(unittest.TestCase):
|
||||||
hashes = []
|
hashes = []
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
code = 'print(hash("spam"))'
|
code = 'print(hash("spam"))'
|
||||||
rc, out, err = assert_python_ok('-R', '-c', code)
|
rc, out, err = assert_python_ok('-c', code)
|
||||||
self.assertEqual(rc, 0)
|
self.assertEqual(rc, 0)
|
||||||
hashes.append(out)
|
hashes.append(out)
|
||||||
self.assertNotEqual(hashes[0], hashes[1])
|
self.assertNotEqual(hashes[0], hashes[1])
|
||||||
|
|
||||||
# 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('-R', '-c', code)
|
rc, out, err = assert_python_ok('-c', code)
|
||||||
self.assertEqual(rc, 0)
|
self.assertEqual(rc, 0)
|
||||||
self.assertIn(b'random is 1', out)
|
self.assertIn(b'random is 1', out)
|
||||||
|
|
||||||
|
|
|
@ -159,8 +159,8 @@ class StringlikeHashRandomizationTests(HashRandomizationTests):
|
||||||
else:
|
else:
|
||||||
known_hash_of_obj = -1600925533
|
known_hash_of_obj = -1600925533
|
||||||
|
|
||||||
# Randomization is disabled by default:
|
# Randomization is enabled by default:
|
||||||
self.assertEqual(self.get_hash(self.repr_), known_hash_of_obj)
|
self.assertNotEqual(self.get_hash(self.repr_), known_hash_of_obj)
|
||||||
|
|
||||||
# It can also be disabled by setting the seed to 0:
|
# It can also be disabled by setting the seed to 0:
|
||||||
self.assertEqual(self.get_hash(self.repr_, seed=0), known_hash_of_obj)
|
self.assertEqual(self.get_hash(self.repr_, seed=0), known_hash_of_obj)
|
||||||
|
|
|
@ -18,10 +18,9 @@ Core and Builtins
|
||||||
- Issue #14051: Allow arbitrary attributes to be set of classmethod and
|
- Issue #14051: Allow arbitrary attributes to be set of classmethod and
|
||||||
staticmethod.
|
staticmethod.
|
||||||
|
|
||||||
- Issue #13703: oCERT-2011-003: add -R command-line option and PYTHONHASHSEED
|
- Issue #13703: oCERT-2011-003: Randomize hashes of str and bytes to protect
|
||||||
environment variable, to provide an opt-in way to protect against denial of
|
against denial of service attacks due to hash collisions within the dict and
|
||||||
service attacks due to hash collisions within the dict and set types. Patch
|
set types. Patch by David Malcolm, based on work by Victor Stinner.
|
||||||
by David Malcolm, based on work by Victor Stinner.
|
|
||||||
|
|
||||||
- Issue #13020: Fix a reference leak when allocating a structsequence object
|
- Issue #13020: Fix a reference leak when allocating a structsequence object
|
||||||
fails. Patch by Suman Saha.
|
fails. Patch by Suman Saha.
|
||||||
|
|
|
@ -37,9 +37,6 @@ python \- an interpreted, interactive, object-oriented programming language
|
||||||
.B \-OO
|
.B \-OO
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
.B \-R
|
|
||||||
]
|
|
||||||
[
|
|
||||||
.B \-s
|
.B \-s
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
|
@ -151,18 +148,6 @@ Discard docstrings in addition to the \fB-O\fP optimizations.
|
||||||
Do not print the version and copyright messages. These messages are
|
Do not print the version and copyright messages. These messages are
|
||||||
also suppressed in non-interactive mode.
|
also suppressed in non-interactive mode.
|
||||||
.TP
|
.TP
|
||||||
.B \-R
|
|
||||||
Turn on "hash randomization", so that the hash() values of str, bytes and
|
|
||||||
datetime objects are "salted" with an unpredictable pseudo-random value.
|
|
||||||
Although they remain constant within an individual Python process, they are
|
|
||||||
not predictable between repeated invocations of Python.
|
|
||||||
.IP
|
|
||||||
This is intended to provide protection against a denial of service
|
|
||||||
caused by carefully-chosen inputs that exploit the worst case performance
|
|
||||||
of a dict insertion, O(n^2) complexity. See
|
|
||||||
http://www.ocert.org/advisories/ocert-2011-003.html
|
|
||||||
for details.
|
|
||||||
.TP
|
|
||||||
.B \-s
|
.B \-s
|
||||||
Don't add user site directory to sys.path.
|
Don't add user site directory to sys.path.
|
||||||
.TP
|
.TP
|
||||||
|
@ -418,9 +403,8 @@ specifying \fB\-v\fP multiple times.
|
||||||
If this is set to a comma-separated string it is equivalent to
|
If this is set to a comma-separated string it is equivalent to
|
||||||
specifying the \fB\-W\fP option for each separate value.
|
specifying the \fB\-W\fP option for each separate value.
|
||||||
.IP PYTHONHASHSEED
|
.IP PYTHONHASHSEED
|
||||||
If this variable is set to "random", the effect is the same as specifying
|
If this variable is set to "random", a random value is used to seed the hashes
|
||||||
the \fB-R\fP option: a random value is used to seed the hashes of str,
|
of str, bytes and datetime objects.
|
||||||
bytes and datetime objects.
|
|
||||||
|
|
||||||
If PYTHONHASHSEED is set to an integer value, it is used as a fixed seed for
|
If PYTHONHASHSEED is set to an integer value, it is used as a fixed seed for
|
||||||
generating the hash() of the types covered by the hash randomization. Its
|
generating the hash() of the types covered by the hash randomization. Its
|
||||||
|
@ -429,8 +413,7 @@ interpreter itself, or to allow a cluster of python processes to share hash
|
||||||
values.
|
values.
|
||||||
|
|
||||||
The integer must be a decimal number in the range [0,4294967295]. Specifying
|
The integer must be a decimal number in the range [0,4294967295]. Specifying
|
||||||
the value 0 will lead to the same hash values as when hash randomization is
|
the value 0 will disable hash randomization.
|
||||||
disabled.
|
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
The Python Software Foundation: http://www.python.org/psf
|
The Python Software Foundation: http://www.python.org/psf
|
||||||
.SH INTERNET RESOURCES
|
.SH INTERNET RESOURCES
|
||||||
|
|
|
@ -73,9 +73,6 @@ static char *usage_2 = "\
|
||||||
-O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\
|
-O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\
|
||||||
-OO : remove doc-strings in addition to the -O optimizations\n\
|
-OO : remove doc-strings in addition to the -O optimizations\n\
|
||||||
-q : don't print version and copyright messages on interactive startup\n\
|
-q : don't print version and copyright messages on interactive startup\n\
|
||||||
-R : use a pseudo-random salt to make hash() values of various types be\n\
|
|
||||||
unpredictable between separate invocations of the interpreter, as\n\
|
|
||||||
a defence against denial-of-service attacks\n\
|
|
||||||
-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
|
-s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
|
||||||
-S : don't imply 'import site' on initialization\n\
|
-S : don't imply 'import site' on initialization\n\
|
||||||
";
|
";
|
||||||
|
@ -107,10 +104,10 @@ static char *usage_5 =
|
||||||
"PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n\
|
"PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n\
|
||||||
";
|
";
|
||||||
static char *usage_6 = "\
|
static char *usage_6 = "\
|
||||||
PYTHONHASHSEED: if this variable is set to ``random``, the effect is the same \n\
|
PYTHONHASHSEED: if this variable is set to ``random``, a random value is used\n\
|
||||||
as specifying the :option:`-R` option: a random value is used to seed the\n\
|
to seed the hashes of str, bytes and datetime objects. It can also be\n\
|
||||||
hashes of str, bytes and datetime objects. It can also be set to an integer\n\
|
set to an integer in the range [0,4294967295] to get hash values with a\n\
|
||||||
in the range [0,4294967295] to get hash values with a predictable seed.\n\
|
predictable seed.\n\
|
||||||
";
|
";
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -347,21 +344,13 @@ Py_Main(int argc, wchar_t **argv)
|
||||||
not interpreter options. */
|
not interpreter options. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (c) {
|
if (c == 'E') {
|
||||||
case 'E':
|
|
||||||
Py_IgnoreEnvironmentFlag++;
|
Py_IgnoreEnvironmentFlag++;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
|
||||||
Py_HashRandomizationFlag++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* The variable is only tested for existence here; _PyRandom_Init will
|
|
||||||
check its value further. */
|
|
||||||
if (!Py_HashRandomizationFlag &&
|
|
||||||
(p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0')
|
|
||||||
Py_HashRandomizationFlag = 1;
|
|
||||||
|
|
||||||
|
Py_HashRandomizationFlag = 1;
|
||||||
_PyRandom_Init();
|
_PyRandom_Init();
|
||||||
|
|
||||||
PySys_ResetWarnOptions();
|
PySys_ResetWarnOptions();
|
||||||
|
@ -468,7 +457,7 @@ Py_Main(int argc, wchar_t **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
/* Already handled above */
|
/* Ignored */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* This space reserved for other options */
|
/* This space reserved for other options */
|
||||||
|
|
|
@ -256,17 +256,6 @@ _PyRandom_Init(void)
|
||||||
return;
|
return;
|
||||||
_Py_HashSecret_Initialized = 1;
|
_Py_HashSecret_Initialized = 1;
|
||||||
|
|
||||||
/*
|
|
||||||
By default, hash randomization is disabled, and only
|
|
||||||
enabled if PYTHONHASHSEED is set to non-empty or if
|
|
||||||
"-R" is provided at the command line:
|
|
||||||
*/
|
|
||||||
if (!Py_HashRandomizationFlag) {
|
|
||||||
/* Disable the randomized hash: */
|
|
||||||
memset(secret, 0, secret_size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Hash randomization is enabled. Generate a per-process secret,
|
Hash randomization is enabled. Generate a per-process secret,
|
||||||
using PYTHONHASHSEED if provided.
|
using PYTHONHASHSEED if provided.
|
||||||
|
|
|
@ -25,7 +25,6 @@ def main(regrtest_args):
|
||||||
'-W', 'default', # Warnings set to 'default'
|
'-W', 'default', # Warnings set to 'default'
|
||||||
'-bb', # Warnings about bytes/bytearray
|
'-bb', # Warnings about bytes/bytearray
|
||||||
'-E', # Ignore environment variables
|
'-E', # Ignore environment variables
|
||||||
'-R', # Randomize hashing
|
|
||||||
]
|
]
|
||||||
# Allow user-specified interpreter options to override our defaults.
|
# Allow user-specified interpreter options to override our defaults.
|
||||||
args.extend(test.support.args_from_interpreter_flags())
|
args.extend(test.support.args_from_interpreter_flags())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue