Skip to content

Commit 13da1a6

Browse files
orenmnserhiy-storchaka
authored andcommitted
[2.7] bpo-31478: Prevent unwanted behavior in _random.Random.seed() in case the arg has a bad __abs__() method (GH-3596) (#3845)
1 parent 20cbc1d commit 13da1a6

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

‎Lib/test/test_random.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,22 @@ def test_randbelow_logic(self, _log=log, int=int):
307307
class MersenneTwister_TestBasicOps(TestBasicOps):
308308
gen = random.Random()
309309

310+
@test_support.cpython_only
311+
def test_bug_31478(self):
312+
# _random.Random.seed() should ignore the __abs__() method of a
313+
# long/int subclass argument.
314+
class BadInt(int):
315+
def __abs__(self):
316+
1/0
317+
class BadLong(long):
318+
def __abs__(self):
319+
1/0
320+
self.gen.seed(42)
321+
expected_value = self.gen.random()
322+
for seed_arg in [42L, BadInt(42), BadLong(42)]:
323+
self.gen.seed(seed_arg)
324+
self.assertEqual(self.gen.random(), expected_value)
325+
310326
def test_setstate_first_arg(self):
311327
self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
312328

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Prevent unwanted behavior in `_random.Random.seed()` in case the argument
2+
has a bad ``__abs__()`` method. Patch by Oren Milman.

‎Modules/_randommodule.c‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,15 @@ random_seed(RandomObject *self, PyObject *args)
230230
}
231231
/* If the arg is an int or long, use its absolute value; else use
232232
* the absolute value of its hash code.
233+
* Calling int.__abs__() or long.__abs__() prevents calling arg.__abs__(),
234+
* which might return an invalid value. See issue #31478.
233235
*/
234-
if (PyInt_Check(arg) || PyLong_Check(arg))
235-
n = PyNumber_Absolute(arg);
236+
if (PyInt_Check(arg)) {
237+
n = PyInt_Type.tp_as_number->nb_absolute(arg);
238+
}
239+
else if (PyLong_Check(arg)) {
240+
n = PyLong_Type.tp_as_number->nb_absolute(arg);
241+
}
236242
else {
237243
long hash = PyObject_Hash(arg);
238244
if (hash == -1)

0 commit comments

Comments
 (0)