Skip to content

Commit 2fb477c

Browse files
committed
Merge 3.2: Issue python#13703 plus some related test suite fixes.
2 parents b5c793a + 9edceb3 commit 2fb477c

38 files changed

Lines changed: 706 additions & 174 deletions

‎Doc/library/sys.rst‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,15 @@ always available.
252252
:const:`verbose` :option:`-v`
253253
:const:`bytes_warning` :option:`-b`
254254
:const:`quiet` :option:`-q`
255+
:const:`hash_randomization` :option:`-R`
255256
============================= =============================
256257

257258
.. versionchanged:: 3.2
258259
Added ``quiet`` attribute for the new :option:`-q` flag.
259260

261+
.. versionadded:: 3.2.3
262+
The ``hash_randomization`` attribute.
263+
260264
.. versionchanged:: 3.3
261265
Removed obsolete ``division_warning`` attribute.
262266

‎Doc/reference/datamodel.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,8 @@ Basic customization
12771277
inheritance of :meth:`__hash__` will be blocked, just as if :attr:`__hash__`
12781278
had been explicitly set to :const:`None`.
12791279

1280+
See also the :option:`-R` command-line option.
1281+
12801282

12811283
.. method:: object.__bool__(self)
12821284

‎Doc/using/cmdline.rst‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Command line
2424

2525
When invoking Python, you may specify any of these options::
2626

27-
python [-bBdEhiOsSuvVWx?] [-c command | -m module-name | script | - ] [args]
27+
python [-bBdEhiORqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
2828

2929
The most common use case is, of course, a simple invocation of a script::
3030

@@ -227,6 +227,29 @@ Miscellaneous options
227227
.. versionadded:: 3.2
228228

229229

230+
.. cmdoption:: -R
231+
232+
Turn on hash randomization, so that the :meth:`__hash__` values of str, bytes
233+
and datetime objects are "salted" with an unpredictable random value.
234+
Although they remain constant within an individual Python process, they are
235+
not predictable between repeated invocations of Python.
236+
237+
This is intended to provide protection against a denial-of-service caused by
238+
carefully-chosen inputs that exploit the worst case performance of a dict
239+
insertion, O(n^2) complexity. See
240+
http://www.ocert.org/advisories/ocert-2011-003.html for details.
241+
242+
Changing hash values affects the order in which keys are retrieved from a
243+
dict. Although Python has never made guarantees about this ordering (and it
244+
typically varies between 32-bit and 64-bit builds), enough real-world code
245+
implicitly relies on this non-guaranteed behavior that the randomization is
246+
disabled by default.
247+
248+
See also :envvar:`PYTHONHASHSEED`.
249+
250+
.. versionadded:: 3.2.3
251+
252+
230253
.. cmdoption:: -s
231254

232255
Don't add the :data:`user site-packages directory <site.USER_SITE>` to
@@ -352,6 +375,7 @@ Options you shouldn't use
352375

353376
.. _Jython: http://jython.org
354377

378+
355379
.. _using-on-envvars:
356380

357381
Environment variables
@@ -460,6 +484,27 @@ These environment variables influence Python's behavior.
460484
option.
461485

462486

487+
.. envvar:: PYTHONHASHSEED
488+
489+
If this variable is set to ``random``, the effect is the same as specifying
490+
the :option:`-R` option: a random value is used to seed the hashes of str,
491+
bytes and datetime objects.
492+
493+
If :envvar:`PYTHONHASHSEED` is set to an integer value, it is used as a fixed
494+
seed for generating the hash() of the types covered by the hash
495+
randomization.
496+
497+
Its purpose is to allow repeatable hashing, such as for selftests for the
498+
interpreter itself, or to allow a cluster of python processes to share hash
499+
values.
500+
501+
The integer must be a decimal number in the range [0,4294967295]. Specifying
502+
the value 0 will lead to the same hash values as when hash randomization is
503+
disabled.
504+
505+
.. versionadded:: 3.2.3
506+
507+
463508
.. envvar:: PYTHONIOENCODING
464509

465510
If this is set before running the interpreter, it overrides the encoding used

‎Include/object.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,12 @@ PyAPI_FUNC(Py_hash_t) _Py_HashPointer(void*);
554554
PyAPI_FUNC(Py_hash_t) _Py_HashBytes(unsigned char*, Py_ssize_t);
555555
#endif
556556

557+
typedef struct {
558+
Py_hash_t prefix;
559+
Py_hash_t suffix;
560+
} _Py_HashSecret_t;
561+
PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret;
562+
557563
/* Helper for passing objects to printf and the like */
558564
#define PyObject_REPR(obj) _PyUnicode_AsString(PyObject_Repr(obj))
559565

‎Include/pydebug.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ PyAPI_DATA(int) Py_IgnoreEnvironmentFlag;
1919
PyAPI_DATA(int) Py_DontWriteBytecodeFlag;
2020
PyAPI_DATA(int) Py_NoUserSiteDirectory;
2121
PyAPI_DATA(int) Py_UnbufferedStdioFlag;
22+
PyAPI_DATA(int) Py_HashRandomizationFlag;
2223

2324
/* this is a wrapper around getenv() that pays attention to
2425
Py_IgnoreEnvironmentFlag. It should be used for getting variables like

‎Include/pythonrun.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ typedef void (*PyOS_sighandler_t)(int);
246246
PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
247247
PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
248248

249+
/* Random */
250+
PyAPI_FUNC(int) _PyOS_URandom (void *buffer, Py_ssize_t size);
249251

250252
#ifdef __cplusplus
251253
}

‎Lib/json/__init__.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
Compact encoding::
3232
3333
>>> import json
34-
>>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',', ':'))
34+
>>> from collections import OrderedDict
35+
>>> mydict = OrderedDict([('4', 5), ('6', 7)])
36+
>>> json.dumps([1,2,3,mydict], separators=(',', ':'))
3537
'[1,2,3,{"4":5,"6":7}]'
3638
3739
Pretty printing::

‎Lib/os.py‎

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -852,23 +852,6 @@ def _pickle_statvfs_result(sr):
852852
except NameError: # statvfs_result may not exist
853853
pass
854854

855-
if not _exists("urandom"):
856-
def urandom(n):
857-
"""urandom(n) -> str
858-
859-
Return a string of n random bytes suitable for cryptographic use.
860-
861-
"""
862-
try:
863-
_urandomfd = open("/dev/urandom", O_RDONLY)
864-
except (OSError, IOError):
865-
raise NotImplementedError("/dev/urandom (or equivalent) not found")
866-
bs = b""
867-
while len(bs) < n:
868-
bs += read(_urandomfd, n - len(bs))
869-
close(_urandomfd)
870-
return bs
871-
872855
# Supply os.popen()
873856
def popen(cmd, mode="r", buffering=-1):
874857
if not isinstance(cmd, str):

‎Lib/test/datetimetester.py‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,8 +1786,6 @@ def test_utcnow(self):
17861786
self.assertTrue(abs(from_timestamp - from_now) <= tolerance)
17871787

17881788
def test_strptime(self):
1789-
import _strptime
1790-
17911789
string = '2004-12-01 13:02:47.197'
17921790
format = '%Y-%m-%d %H:%M:%S.%f'
17931791
expected = _strptime._strptime_datetime(self.theclass, string, format)

‎Lib/test/mapping_tests.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class BasicTestMappingProtocol(unittest.TestCase):
1414
def _reference(self):
1515
"""Return a dictionary of values which are invariant by storage
1616
in the object under test."""
17-
return {1:2, "key1":"value1", "key2":(1,2,3)}
17+
return {"1": "2", "key1":"value1", "key2":(1,2,3)}
1818
def _empty_mapping(self):
1919
"""Return an empty mapping object"""
2020
return self.type2test()

0 commit comments

Comments
 (0)