Skip to content

gh-119395: Fix leaky mangling after generic classes #119399

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
wants to merge 4 commits into from

Conversation

JelleZijlstra
Copy link
Member

@JelleZijlstra JelleZijlstra commented May 22, 2024

class Outer:
__before = "before"
class Inner[T]:
__x = "inner"
Copy link
Member

Choose a reason for hiding this comment

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

Is it a good idea to test __before = "class"; __after = "class" names in the class scope here? Or do we have them tested?

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean in the inner class? That wouldn't really be relevant here since there is nothing else interesting going on in the inner class body.

Python/compile.c Outdated
@@ -2624,6 +2624,7 @@ compiler_class(struct compiler *c, stmt_ty s)

asdl_type_param_seq *type_params = s->v.ClassDef.type_params;
int is_generic = asdl_seq_LEN(type_params) > 0;
PyObject *old_u_private = Py_XNewRef(c->u->u_private);
if (is_generic) {
Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
Copy link
Member

@carljm carljm May 22, 2024

Choose a reason for hiding this comment

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

The save-restore pattern is not needed or used in compiler_class_body, because there c->u->u_private is set after compiler_enter_scope, so it is set only on the inner compiler unit, not the outer one.

Setting it on the outer compiler unit works here, because compiler_enter_scope copies it to inner scopes. But is it required to set it on the outer unit? I don't see anything happening between here and the compiler_enter_scope call that seems to require mangling?

If we move this line down to after compiler_enter_scope, does that work and fix the bug, without requiring save/restore? If so, that seems simpler and more consistent with the intended/existing pattern for handling u_private.

@@ -1673,13 +1672,15 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
VISIT_QUIT(st, 0);
if (s->v.ClassDef.decorator_list)
VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
PyObject *old_st_private = st->st_private;
Copy link
Member

Choose a reason for hiding this comment

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

I don't care too much either way, but I think it would be equivalent and simpler to move the existing pair of lines

tmp = st->st_private;
st->st_private = s->v.ClassDef.name;

up to right here. We want to unconditionally set it to the same thing either way.

If it's a problem to have st_private set during lines 1686 to 1691, then that would imply that your current version is problematic as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

That would introduce the #119311 bug to non-generic classes too. However, you're right that this can be simplified. I'm about to open an alternative PR that fixes both this and #119311.

@JelleZijlstra
Copy link
Member Author

#119464 supersedes this PR, but keeping this one open for now since we may want to apply this change in 3.12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs backport to 3.12 only security fixes needs backport to 3.13 bugs and security fixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants