Commit c9f54cf5 authored by Benjamin Peterson's avatar Benjamin Peterson

enable hash randomization by default

parent 6ca5a4d4
...@@ -1277,7 +1277,29 @@ Basic customization ...@@ -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 ...@@ -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. ...@@ -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. ...@@ -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): ...@@ -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): ...@@ -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 ...@@ -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 ...@@ -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. ...@@ -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. ...@@ -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 ...@@ -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 = "\ ...@@ -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 = ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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): ...@@ -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())
......
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