Skip to content

gh-151515: Fix incorrect function pointer cast in asdl_c.py generator#151514

Open
CoderSilicon wants to merge 6 commits into
python:mainfrom
CoderSilicon:patch-1
Open

gh-151515: Fix incorrect function pointer cast in asdl_c.py generator#151514
CoderSilicon wants to merge 6 commits into
python:mainfrom
CoderSilicon:patch-1

Conversation

@CoderSilicon

@CoderSilicon CoderSilicon commented Jun 15, 2026

Copy link
Copy Markdown

Summary

This PR fixes an undefined behavior bug in the C code generated by Parser/asdl_c.py for get_ast_state().

The Problem

In the generated code, _PyOnceFlag_CallOnce is invoked like this:
_PyOnceFlag_CallOnce(&state->once, (_Py_once_fn_t *)&init_types, state)

Using &init_types passes a pointer to a function pointer (effectively a double pointer), rather than the function pointer itself. by forcing this with an explicit cast (_Py_once_fn_t *) silences the compiler but triggers a strict aliasing violation and undefined behavior at runtime when the pointer is dereferenced. This can lead to compiler-optimization-driven segmentation faults, particularly in free-threaded/GIL-disabled builds where one-time initialization flags are heavily relied upon.

The Fix

Updated Parser/asdl_c.py to pass init_types directly with a standard function pointer cast (_Py_once_fn_t)init_types (removing the extra & and *). Ran make regen-ast to cleanly update the generated files.

@bedevere-app

bedevere-app Bot commented Jun 15, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@bedevere-app

bedevere-app Bot commented Jun 15, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@CoderSilicon CoderSilicon changed the title gh-00000: Fix incorrect function pointer cast in asdl_c.py generator gh-#151515: Fix incorrect function pointer cast in asdl_c.py generator Jun 15, 2026
@CoderSilicon CoderSilicon changed the title gh-#151515: Fix incorrect function pointer cast in asdl_c.py generator gh-151515: Fix incorrect function pointer cast in asdl_c.py generator Jun 15, 2026

@picnixz picnixz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Plsease revert all cosmetic changes in this PR. Only change the part that may need to change.

@bedevere-app

bedevere-app Bot commented Jun 15, 2026

Copy link
Copy Markdown

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.

Comment thread Parser/asdl_c.py
struct ast_state *state = &interp->ast;
assert(!state->finalized);
if (_PyOnceFlag_CallOnce(&state->once, (_Py_once_fn_t *)&init_types, state) < 0) {
if (_PyOnceFlag_CallOnce(&state->once, (_Py_once_fn_t)init_types, state) < 0) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The symbol init_types is declared a few lines up as a function, not a variable, so regardless of whether you take its address (&init_types) or not, you always get a pointer to the function.

From Include/internal/pycore_lock.h, _Py_once_fn_t is a function (signature) type, not a function pointer type:

typedef int _Py_once_fn_t(void *arg);

I don’t think it is valid to cast to a function type.

I don’t see how the original code produces undefined behaviour. However, why not just remove the cast?

Suggested change
if (_PyOnceFlag_CallOnce(&state->once, (_Py_once_fn_t)init_types, state) < 0) {
if (_PyOnceFlag_CallOnce(&state->once, &init_types, state) < 0) {

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