diff -r ca1ddd365f5f Lib/random.py --- a/Lib/random.py Sat Aug 27 04:00:19 2016 +0000 +++ b/Lib/random.py Wed Aug 31 23:09:05 2016 +0300 @@ -110,7 +110,14 @@ a = int.from_bytes(_urandom(2500), 'big') except NotImplementedError: import time - a = int(time.time() * 256) # use fractional seconds + a = int(time.time() * 256) # use fractional seconds + + if version == 1 and isinstance(a, (str, bytes)): + x = ord(a[0]) << 7 if a else 0 + for c in a: + x = ((1000003 * x) ^ ord(c)) & 0xFFFFFFFFFFFFFFFF + x ^= len(a) + a = -2 if x == -1 else x if version == 2: if isinstance(a, (str, bytes, bytearray)): diff -r ca1ddd365f5f Lib/test/test_random.py --- a/Lib/test/test_random.py Sat Aug 27 04:00:19 2016 +0000 +++ b/Lib/test/test_random.py Wed Aug 31 23:09:05 2016 +0300 @@ -323,8 +323,26 @@ '0x1.1ebb4352e4c4dp-1', '0x1.1a7422abf9c11p-1']) self.gen.seed("the quick brown fox", version=2) self.assertEqual([self.gen.random().hex() for i in range(4)], - ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4', - '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1']) + ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4', + '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1']) + + def test_bug_27706(self): + # Verify that version 1 seeds are unaffected by hash randomization + + self.gen.seed('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('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('', 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']) def test_setstate_first_arg(self): self.assertRaises(ValueError, self.gen.setstate, (1, None, None)) @@ -533,6 +551,7 @@ self.assertTrue(stop < x <= start) self.assertEqual((x+stop)%step, 0) + def gamma(z, sqrt2pi=(2.0*pi)**0.5): # Reflection to right half of complex plane if z < 0.5: @@ -761,6 +780,8 @@ random.Random.__init__(self) Subclass(newarg=1) + def test_setstate_first_arg(self): + self.assertRaises(ValueError, self.gen.setstate, (1, None, None)) if __name__ == "__main__": unittest.main()