Skip to content

Conversation

@priyanshu2282-cyber
Copy link
Contributor

@priyanshu2282-cyber priyanshu2282-cyber commented Jan 13, 2026

__index__ can change the array’s class during multiplication. After that,
the old function is still called, which can cause a crash. This adds a
check to avoid that and raises TypeError instead.

A regression test is also added.

@bedevere-app

This comment was marked as resolved.

@bedevere-app

This comment was marked as resolved.

@priyanshu2282-cyber
Copy link
Contributor Author

Thanks, fixed.

@@ -9716,13 +9714,19 @@ 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

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.

Copy link
Member

@picnixz picnixz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to make those changes in typeobject? is it only relevant for objects implementing __mul__? or is it relevant only to array.__mul__?

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

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?

@bedevere-app
Copy link

bedevere-app bot commented Jan 13, 2026

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@priyanshu2282-cyber
Copy link
Contributor Author

The change in typeobject.c is intentional. This didn’t seem specific to array.__mul__ , since wrap_indexargfunc is part of the generic numeric machinery, because user code runs during __index__, similar issues could show up in other numeric operations as well.

@skirpichev
Copy link
Member

This didn’t seem specific to array.mul

Does it happens e.g. for lists, which also implement sq_repeat slot?

@priyanshu2282-cyber
Copy link
Contributor Author

I am not aware of this if it happens with lists. The crash seems to be array-specific, and lists don’t appear to reach this broken state in practice.

@picnixz
Copy link
Member

picnixz commented Jan 14, 2026

I am not aware of this if it happens with lists. The crash seems to be array-specific, and lists don’t appear to reach this broken state in practice.

And thus this means that the issue is with array.__mul__. We are likely taking a borrowed reference somewhere instead which explains why the incref on the type is needed.

@picnixz
Copy link
Member

picnixz commented Jan 14, 2026

Or more generally, looks like an issue with getting the module's state. However I'm pretty sure it could affect other subclassable heap types.

@skirpichev
Copy link
Member

looks like an issue with getting the module's state

Yes, get_array_state() get NULL, from unchecked return value of PyType_GetModuleByDef().

@picnixz
Copy link
Member

picnixz commented Jan 14, 2026

I'm closing this PR because the approach is incorrect. We should be careful when accessing state of subclassable heap type objects. I think it would be better if we addressed this for all heap types simultaneously. I'm travelling for the next 2 weeks so I won't be able to do it but a pre-emptive investigation on which types suffer from that would be good.

@picnixz picnixz closed this Jan 14, 2026
@picnixz
Copy link
Member

picnixz commented Jan 14, 2026

On a simlar note, I've tried to design some (internal) functions for safely getting the module's state from an object or its type, because currently, we need to do multiple calls and it's not always clear whether the caller knows which function to use (with/wo underscores? with/wo checks? etc)

@priyanshu2282-cyber
Copy link
Contributor Author

Thanks for the explanation, that makes sense. I understand why a more general solution would be preferable here. Appreciate the feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants