-
-
Notifications
You must be signed in to change notification settings - Fork 33.9k
gh-142883: avoid crash when __index__ changes array type during multiplication. #143776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
19e1acb
f41021e
c70d8a8
fc92210
4ad938d
e444a1f
5db8477
4b1f1ac
a610d9f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -226,5 +226,30 @@ def test_complex(self): | |
| self.assertRaises(TypeError, op, v, z) | ||
|
|
||
|
|
||
| class IndexMutationDuringNumericOpTest(unittest.TestCase): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it in the numeric tower??? it has nothing to do with numeric tower.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I initially added the test to test_numeric_tower.py since the problem shows up during a numeric operation and involves |
||
| def test_index_mutates_lhs_type_during_operation(self): | ||
| import array | ||
|
|
||
| class Good(array.array): | ||
| pass | ||
|
|
||
| class Hide(type): | ||
| def mro(cls): | ||
| return (cls, object) | ||
|
|
||
| class Bad(Good, metaclass=Hide): | ||
| pass | ||
|
|
||
| arr = Good('b', b'x') | ||
|
|
||
| class Count: | ||
| def __index__(self): | ||
| arr.__class__ = Bad | ||
| return 2 | ||
|
|
||
| with self.assertRaises(TypeError): | ||
| arr * Count() | ||
priyanshu2282-cyber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Fixed a crash during array multiplication when ``__index__`` changes the | ||
| array’s class while the operation is in progress. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9714,13 +9714,26 @@ wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) | |
| ssizeargfunc func = (ssizeargfunc)wrapped; | ||
| PyObject* o; | ||
| Py_ssize_t i; | ||
| PyTypeObject *type_before = Py_TYPE(self); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not very sure about this, but I'm wondering should we increase the refcount for
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that makes sense. Since we call user code next, the type could indeed be GCed if its last reference is dropped. I’ve updated the code to INCREF |
||
| Py_INCREF(type_before); | ||
|
|
||
| if (!check_num_args(args, 1)) | ||
| if (!check_num_args(args, 1)){ | ||
| Py_DECREF(type_before); | ||
| return NULL; | ||
| } | ||
| o = PyTuple_GET_ITEM(args, 0); | ||
| i = PyNumber_AsSsize_t(o, PyExc_OverflowError); | ||
| if (i == -1 && PyErr_Occurred()) | ||
| if (i == -1 && PyErr_Occurred()){ | ||
| Py_DECREF(type_before); | ||
| return NULL; | ||
| } | ||
| if (Py_TYPE(self) != type_before) { | ||
| Py_DECREF(type_before); | ||
| PyErr_SetString(PyExc_TypeError, | ||
| "object mutated during numeric operation"); | ||
| return NULL; | ||
| } | ||
| Py_DECREF(type_before); | ||
| return (*func)(self, i); | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.