Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
9 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Lib/test/test_numeric_tower.py
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -226,5 +226,30 @@ def test_complex(self):
self.assertRaises(TypeError, op, v, z)


class IndexMutationDuringNumericOpTest(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

@priyanshu2282-cyber priyanshu2282-cyber Jan 13, 2026

Choose a reason for hiding this comment

The 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 __index__ being called. That’s why it felt like a reasonable place to put it at first, but I’m happy to move it. Is there a test module you would prefer for this regression test?

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()


if __name__ == '__main__':
unittest.main()
View file Open in desktop
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.
17 changes: 15 additions & 2 deletions Objects/typeobject.c
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The 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 type_before, because we will call user's code next, thus it may be GCed (like user delete the type in __index__)?

Copy link
Contributor Author

@priyanshu2282-cyber priyanshu2282-cyber Jan 13, 2026

Choose a reason for hiding this comment

The 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 type_before before calling user code and DECREF it on all exit paths. I also ran the regression test locally and it passes.

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);
}

Expand Down
Loading

AltStyle によって変換されたページ (->オリジナル) /