Skip to content

Conversation

@skirpichev
Copy link
Contributor

@skirpichev skirpichev commented Jan 3, 2026

Added a mutex flag to trigger RuntimeError if Struct() modification happens during packing.

@skirpichev skirpichev force-pushed the fix-uaf-s_pack_internal/143379 branch from 0bfe0a3 to a1c2603 Compare January 3, 2026 07:36
@skirpichev skirpichev requested a review from vstinner January 3, 2026 07:41
@skirpichev
Copy link
Contributor Author

Alternative approach: use some flag in PyStructObject struct to forbid mutation during pack().

@vstinner
Copy link
Member

vstinner commented Jan 5, 2026

Alternative approach: use some flag in PyStructObject struct to forbid mutation during pack().

Would it be possible to always disallow mutation? Raise an exception if __init__() is called twice.

@skirpichev
Copy link
Contributor Author

Why there is __init__() method at all? The Struct expected to be an immutable type.

Maybe all logic in Struct___init__ (tp_init) should be moved to s_new (tp_new)? I think this will fix issue. Looking in the history, the custom __init__() was re-introduced back in #112358.

Here is the plan:

  1. create a flag to temporary forbid mutation
  2. deprecate Struct.__new__() calls without one required argument
  3. eventually drop Struct.__init__() together with a flag

CC @serhiy-storchaka

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

This is too complicated and expensive.

Would not it be easier to forbid calling __init__() more than once? This can break some weird code, so as an intermediate solution we can add a mutex flag which forbids calling __init__() when the object is used.

@serhiy-storchaka
Copy link
Member

Seen #143382 (comment) after trying to review the code. I agree with @skirpichev, a flag is the right temporary solution, and we should think about getting rid of __init__() in future.

@skirpichev skirpichev marked this pull request as draft January 9, 2026 11:41
@skirpichev skirpichev marked this pull request as ready for review January 10, 2026 02:35
@skirpichev
Copy link
Contributor Author

skirpichev commented Jan 10, 2026

Ok, new version just disallows mutation of Struct() when s_pack_internal() is running. When support for __init__() will be dropped - the mutex field can be removed.

Edit: see #143643 for next steps.

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

Would not it prevent concurrent use of pack()? It would be undesirable. We need a counter (atomic for GIL-less build) which would allow concurrent operations, but block __init__(). Please test how it affects performance.

To be absolutely safe, we would need also a mutex which would block packing while __init__() is executed. Because there is a race condition between checking if it is safe to modify the struct state and modifying it. But it is very unlikely to happen in real world (why would anybody call __init__() concurrently with pack()?), so we can ignore this for now. Well, ignoring this issue until we forbid repeated calls of __init__() is also solution.

@skirpichev
Copy link
Contributor Author

Would not it prevent concurrent use of pack()?

Hmm, indeed.

Well, ignoring this issue until we forbid repeated calls of init() is also solution.

We can do this after a deprecation (see ongoing work in #143643). But then this will be a non-issue anymore. Then, maybe we can close the #143379 as a duplicate of #78724? The real problem here is that Struct()'s aren't immutable.

skirpichev added a commit to skirpichev/cpython that referenced this pull request Jan 10, 2026
@skirpichev skirpichev marked this pull request as draft January 10, 2026 12:11
@skirpichev skirpichev marked this pull request as ready for review January 11, 2026 02:15
@skirpichev
Copy link
Contributor Author

Ok, this lacks mutex in __init__() and benchmarks. But I'll not push things further. Thanks for review.

@skirpichev skirpichev closed this Jan 11, 2026
@skirpichev skirpichev deleted the fix-uaf-s_pack_internal/143379 branch January 11, 2026 02:19
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.

3 participants