From d780b2d588e68bd7047ef5d1f04e36da38b7a350 Mon Sep 17 00:00:00 2001 From: Oren Milman Date: Thu, 28 Sep 2017 10:50:01 +0300 Subject: [PATCH] bpo-31478: Fix an assertion failure in random.seed() in case a seed has a bad __abs__() method. (#3596) --- Lib/test/test_random.py | 11 +++++++++++ .../2017-09-15-09-13-07.bpo-31478.o06iKD.rst | 2 ++ Modules/_randommodule.c | 7 +++++-- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-09-15-09-13-07.bpo-31478.o06iKD.rst diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 5d12aee169..e2db72330c 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -430,6 +430,17 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1', '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2']) + def test_bug_31478(self): + # There shouldn't be an assertion failure in _random.Random.seed() in + # case the argument has a bad __abs__() method. + class BadInt(int): + def __abs__(self): + return None + try: + self.gen.seed(BadInt()) + except TypeError: + pass + 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. diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-15-09-13-07.bpo-31478.o06iKD.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-15-09-13-07.bpo-31478.o06iKD.rst new file mode 100644 index 0000000000..bbeb810eba --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-15-09-13-07.bpo-31478.o06iKD.rst @@ -0,0 +1,2 @@ +Fix an assertion failure in `_random.Random.seed()` in case the argument has a +bad ``__abs__()`` method. Patch by Oren Milman. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 747a547342..51677f8b00 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -259,8 +259,11 @@ random_seed(RandomObject *self, PyObject *args) * So: if the arg is a PyLong, use its absolute value. * Otherwise use its hash value, cast to unsigned. */ - if (PyLong_Check(arg)) - n = PyNumber_Absolute(arg); + if (PyLong_Check(arg)) { + /* Calling int.__abs__() prevents calling arg.__abs__(), which might + return an invalid value. See issue #31478. */ + n = PyLong_Type.tp_as_number->nb_absolute(arg); + } else { Py_hash_t hash = PyObject_Hash(arg); if (hash == -1) -- 2.40.0