From: Raymond Hettinger Date: Sun, 17 Sep 2017 16:04:30 +0000 (-0700) Subject: bpo-31482: Missing bytes support for random.seed() version 1 (#3614) X-Git-Tag: v3.7.0a1~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=132a7d7cdbc7cb89fa1c1f4e8192241c3d68f549;p=python bpo-31482: Missing bytes support for random.seed() version 1 (#3614) bpo-31482: Missing bytes support for random.seed() version 1 #3614 --- diff --git a/Lib/random.py b/Lib/random.py index 01c0c3d25f..91065b7e30 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -110,9 +110,10 @@ class Random(_random.Random): """ if version == 1 and isinstance(a, (str, bytes)): + a = a.decode('latin-1') if isinstance(a, bytes) else a x = ord(a[0]) << 7 if a else 0 - for c in a: - x = ((1000003 * x) ^ ord(c)) & 0xFFFFFFFFFFFFFFFF + for c in map(ord, a): + x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF x ^= len(a) a = -2 if x == -1 else x diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index fbb1cf6696..5d12aee169 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -430,6 +430,33 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1', '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2']) + def test_bug_31482(self): + # Verify that version 1 seeds are unaffected by hash randomization + # when the seeds are expressed as bytes rather than strings. + # The hash(b) values listed are the Python2.7 hash() values + # which were used for seeding. + + self.gen.seed(b'nofar', version=1) # hash('nofar') == 5990528763808513177 + self.assertEqual([self.gen.random().hex() for i in range(4)], + ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5', + '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6']) + + self.gen.seed(b'rachel', version=1) # hash('rachel') == -9091735575445484789 + self.assertEqual([self.gen.random().hex() for i in range(4)], + ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3', + '0x1.3052b9c072678p-2', '0x1.578f332106574p-3']) + + self.gen.seed(b'', version=1) # hash('') == 0 + self.assertEqual([self.gen.random().hex() for i in range(4)], + ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1', + '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2']) + + b = b'\x00\x20\x40\x60\x80\xA0\xC0\xE0\xF0' + self.gen.seed(b, version=1) # hash(b) == 5015594239749365497 + self.assertEqual([self.gen.random().hex() for i in range(4)], + ['0x1.52c2fde444d23p-1', '0x1.875174f0daea4p-2', + '0x1.9e9b2c50e5cd2p-1', '0x1.fa57768bd321cp-2']) + def test_setstate_first_arg(self): self.assertRaises(ValueError, self.gen.setstate, (1, None, None)) diff --git a/Misc/NEWS.d/next/Library/2017-09-16-01-53-11.bpo-31482.39s5dS.rst b/Misc/NEWS.d/next/Library/2017-09-16-01-53-11.bpo-31482.39s5dS.rst new file mode 100644 index 0000000000..ed7a4175cd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-16-01-53-11.bpo-31482.39s5dS.rst @@ -0,0 +1 @@ +``random.seed()`` now works with bytes in version=1