Issue 31478: assertion failure in random.seed() in case the seed argument has a bad abs() method (original) (raw)

Created on 2017-09-14 20:33 by Oren Milman, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 3596 merged Oren Milman,2017-09-15 09:34
PR 3794 merged serhiy.storchaka,2017-09-28 07:52
PR 3845 merged Oren Milman,2017-10-01 13:51
Messages (13)
msg302208 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-09-14 20:33
The following code causes an assertion failure: class BadInt(int): def __abs__(self): return None import random random.seed(BadInt()) this is because random_seed() (in Modules/_randommodule.c) assumes that PyNumber_Absolute() returned an int, and so it passes it to _PyLong_NumBits(), which asserts it received an int. what should we do in such a case? should we raise an exception? (the docs don't mention abs() in case the seed is an int - https://docs.python.org/3.7/library/random.html#random.seed)
msg302228 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-09-15 02:01
It would make sense to verify that an actual int was returned and to raise a TypeError if it wasn't. Do you want to submit a PR (with a test case)?
msg302232 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-09-15 05:02
sure. but what about the TypeError message? should it complain about the return value of abs(seed)? (the docs of random.seed don't mention abs().)
msg302234 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-09-15 06:08
There are several ways of solving this issue: 1. Verify that an actual int was returned and raise a TypeError if it wasn't. 2. Verify that an actual int was returned and fall back to the hash if it wasn't. 3. Use int.__abs__() instead of abs(), the result will be guaranteed int. The drawback is that this makes a copy of positive integers for int subclasses. 4. Check the sign of the seed and call int.__neg__() for negative values.
msg302241 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-09-15 09:35
i opened a PR that implements the first option, but of course I wouldn't mind if you decide another option is better.
msg302317 - (view) Author: Vedran Čačić (veky) * Date: 2017-09-16 03:40
So floats (and complexes) cannot be seeds anymore? :-o Or this pertains only to ints? In this case, I think the easiest doc fix is to change If a is an int, it is used directly. to If a is an int, its absolute value is used.
msg302740 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-09-22 08:43
The more I think about this the more I like the idea of using int.__abs__() directly (PyLong_Type.tp_as_number->nb_absolute() in C). The C code doesn't call potentially overridable methods bit_length() and to_bytes(), it uses concrete implementations directly. I don't see reasons why it should obey overriding the __abs__() method. This will save us from the problem with the wording of the error message. I mentioned a drawback, but the current implementation has the same drawback. We can avoid copying positive integer subtypes by using more complex code, but I think it isn't worth.
msg302782 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-09-23 04:57
> I don't see reasons why it should obey overriding the __abs__() method. I concur.
msg303196 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-09-28 07:50
New changeset d780b2d588e68bd7047ef5d1f04e36da38b7a350 by Serhiy Storchaka (Oren Milman) in branch 'master': bpo-31478: Fix an assertion failure in random.seed() in case a seed has a bad __abs__() method. (#3596) https://github.com/python/cpython/commit/d780b2d588e68bd7047ef5d1f04e36da38b7a350
msg303201 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-09-28 09:17
New changeset befc956acf8ddeb94f000ed081ddec51315429e5 by Serhiy Storchaka in branch '3.6': [3.6] bpo-31478: Fix an assertion failure in random.seed() in case a seed has a bad __abs__() method. (GH-3596) (#3794) https://github.com/python/cpython/commit/befc956acf8ddeb94f000ed081ddec51315429e5
msg303207 - (view) Author: Oren Milman (Oren Milman) * Date: 2017-09-28 10:22
With regard to backporting to 2.7: In 2.7 also, PyNumber_Absolute() is called, and its return value is stored in the variable n. However, there is no _PyLong_NumBits(n), so there is no assertion failure. If n isn't an integer: - if !PyObject_IsTrue(n), then the seed is zero (e.g. if n is None, [], () or {}) - otherwise, PyNumber_And() and PyNumber_Rshift() are used in a loop on n, so probably a TypeError would be raised. So I think a backport is still desirable, but i am not sure about the test. Maybe we should use @cpython_only, and make sure that no error is raised? We can also make sure that random() returns a different value than when the seed is zero. What do you think?
msg303451 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-10-01 06:46
I agree that a backport is still desirable. Your plan LGTM. Implement __abs__ raising an exception (test both int ant long subclasses). Make sure that no error is raised. Make sure that random() returns the same value as when seeding with an exact int and long.
msg303566 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-10-02 21:31
New changeset 13da1a60f13e173f65bb0da5ab325641d5bb99ec by Serhiy Storchaka (Oren Milman) in branch '2.7': [2.7] bpo-31478: Prevent unwanted behavior in _random.Random.seed() in case the arg has a bad __abs__() method (GH-3596) (#3845) https://github.com/python/cpython/commit/13da1a60f13e173f65bb0da5ab325641d5bb99ec
History
Date User Action Args
2022-04-11 14:58:52 admin set github: 75659
2017-10-02 21:35:15 serhiy.storchaka set status: open -> closedresolution: fixedstage: patch review -> resolved
2017-10-02 21:31:47 serhiy.storchaka set messages: +
2017-10-01 13:51:06 Oren Milman set pull_requests: + <pull%5Frequest3826>
2017-10-01 06:47:00 serhiy.storchaka set messages: +
2017-09-28 10:22:44 Oren Milman set messages: +
2017-09-28 09:17:56 serhiy.storchaka set messages: +
2017-09-28 07:52:09 serhiy.storchaka set pull_requests: + <pull%5Frequest3778>
2017-09-28 07:50:06 serhiy.storchaka set messages: +
2017-09-23 04:57:42 rhettinger set messages: +
2017-09-22 08:43:32 serhiy.storchaka set messages: + versions: + Python 2.7, Python 3.6
2017-09-16 03:40:36 veky set nosy: + vekymessages: +
2017-09-15 09:35:33 Oren Milman set messages: +
2017-09-15 09:34:19 Oren Milman set keywords: + patchstage: patch reviewpull_requests: + <pull%5Frequest3587>
2017-09-15 06:08:56 serhiy.storchaka set messages: +
2017-09-15 05:02:02 Oren Milman set messages: +
2017-09-15 02:01:36 rhettinger set nosy: + serhiy.storchaka, rhettingermessages: +
2017-09-14 20:33:46 Oren Milman create