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

Appearance settings

Commit 70c7796

Browse filesBrowse files
authored
gh-104619: never leak comprehension locals to outer locals() (#104637)
1 parent 86e6f16 commit 70c7796
Copy full SHA for 70c7796

File tree

Expand file treeCollapse file tree

2 files changed

+32
-21
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+32
-21
lines changed

‎Lib/test/test_listcomps.py

Copy file name to clipboardExpand all lines: Lib/test/test_listcomps.py
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,19 @@ def test_assign_to_comp_iter_var_in_outer_function(self):
516516
"""
517517
self._check_in_scopes(code, {"a": [1]}, scopes=["function"])
518518

519+
def test_no_leakage_to_locals(self):
520+
code = """
521+
def b():
522+
[a for b in [1] for _ in []]
523+
return b, locals()
524+
r, s = b()
525+
x = r is b
526+
y = list(s.keys())
527+
"""
528+
self._check_in_scopes(code, {"x": True, "y": []}, scopes=["module"])
529+
self._check_in_scopes(code, {"x": True, "y": ["b"]}, scopes=["function"])
530+
self._check_in_scopes(code, raises=NameError, scopes=["class"])
531+
519532

520533
__test__ = {'doctests' : doctests}
521534

‎Python/compile.c

Copy file name to clipboardExpand all lines: Python/compile.c
+19-21Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5490,31 +5490,29 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
54905490
}
54915491
Py_DECREF(outv);
54925492
}
5493-
if (outsc == LOCAL || outsc == CELL || outsc == FREE) {
5494-
// local names bound in comprehension must be isolated from
5495-
// outer scope; push existing value (which may be NULL if
5496-
// not defined) on stack
5493+
// local names bound in comprehension must be isolated from
5494+
// outer scope; push existing value (which may be NULL if
5495+
// not defined) on stack
5496+
if (state->pushed_locals == NULL) {
5497+
state->pushed_locals = PyList_New(0);
54975498
if (state->pushed_locals == NULL) {
5498-
state->pushed_locals = PyList_New(0);
5499-
if (state->pushed_locals == NULL) {
5500-
return ERROR;
5501-
}
5502-
}
5503-
// in the case of a cell, this will actually push the cell
5504-
// itself to the stack, then we'll create a new one for the
5505-
// comprehension and restore the original one after
5506-
ADDOP_NAME(c, loc, LOAD_FAST_AND_CLEAR, k, varnames);
5507-
if (scope == CELL) {
5508-
if (outsc == FREE) {
5509-
ADDOP_NAME(c, loc, MAKE_CELL, k, freevars);
5510-
} else {
5511-
ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars);
5512-
}
5513-
}
5514-
if (PyList_Append(state->pushed_locals, k) < 0) {
55155499
return ERROR;
55165500
}
55175501
}
5502+
// in the case of a cell, this will actually push the cell
5503+
// itself to the stack, then we'll create a new one for the
5504+
// comprehension and restore the original one after
5505+
ADDOP_NAME(c, loc, LOAD_FAST_AND_CLEAR, k, varnames);
5506+
if (scope == CELL) {
5507+
if (outsc == FREE) {
5508+
ADDOP_NAME(c, loc, MAKE_CELL, k, freevars);
5509+
} else {
5510+
ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars);
5511+
}
5512+
}
5513+
if (PyList_Append(state->pushed_locals, k) < 0) {
5514+
return ERROR;
5515+
}
55185516
}
55195517
}
55205518
if (state->pushed_locals) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.