Skip to content

Commit 0741417

Browse files
committed
Avoid leaking null to __dict__ when unbinding except var
1 parent 36a0812 commit 0741417

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_exception.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,11 @@ class A: pass
634634
except UnicodeEncodeError as e:
635635
errMsg = str(e)
636636
assert len(errMsg) > 0
637+
638+
def test_exception_scope(self):
639+
g = {}
640+
exec("try:1\nexcept Exception as e: pass", g)
641+
assert 'e' not in g
642+
exec("try:1/0\nexcept Exception as e: pass", g)
643+
assert 'e' not in g
644+

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptNode.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,23 @@
6464
public class ExceptNode extends PNodeWithContext implements InstrumentableNode {
6565
@Child private StatementNode body;
6666
@Child private WriteNode exceptName;
67+
@Child private StatementNode exceptNameDelete;
6768
@Child private ExpressionNode exceptType;
6869

6970
@Child private ExceptMatchNode matchNode;
7071

71-
public ExceptNode(StatementNode body, ExpressionNode exceptType, WriteNode exceptName) {
72+
public ExceptNode(StatementNode body, ExpressionNode exceptType, WriteNode exceptName, StatementNode exceptNameDelete) {
7273
this.body = body;
7374
this.exceptName = exceptName;
7475
this.exceptType = exceptType;
76+
this.exceptNameDelete = exceptNameDelete;
7577
}
7678

7779
public ExceptNode(ExceptNode original) {
7880
this.body = original.body;
7981
this.exceptName = original.exceptName;
8082
this.exceptType = original.exceptType;
83+
this.exceptNameDelete = original.exceptNameDelete;
8184
}
8285

8386
public void executeExcept(VirtualFrame frame, Throwable e) {
@@ -90,7 +93,7 @@ public void executeExcept(VirtualFrame frame, Throwable e) {
9093
}
9194
body.executeVoid(frame);
9295
if (exceptName != null) {
93-
exceptName.executeObject(frame, null);
96+
exceptNameDelete.executeVoid(frame);
9497
}
9598
throw ExceptionHandledException.INSTANCE;
9699
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/sst/FactorySSTVisitor.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,17 @@ private void delTarget(List<StatementNode> blockList, PNode target) {
711711
}
712712
}
713713

714+
protected StatementNode unbindVariable(ReadNode target) {
715+
if (target instanceof ReadLocalNode) {
716+
return ((ReadLocalNode) target).makeDeleteNode();
717+
} else if (target instanceof ReadGlobalOrBuiltinNode) {
718+
return DeleteGlobalNode.create(((ReadGlobalOrBuiltinNode) target).getAttributeId());
719+
} else if (target instanceof ReadNameNode) {
720+
return DeleteNameNode.create(((ReadNameNode) target).getAttributeId());
721+
}
722+
throw new IllegalStateException("invalid target for unbind");
723+
}
724+
714725
@Override
715726
public PNode visit(ExceptSSTNode node) {
716727
// we shouldn't visit this node. It should be processed in try
@@ -1253,8 +1264,14 @@ public PNode visit(TrySSTNode node) {
12531264
}
12541265
ExpressionNode exceptTest = exceptNode.test != null ? (ExpressionNode) exceptNode.test.accept(this) : null;
12551266
StatementNode exceptBody = (StatementNode) exceptNode.body.accept(this);
1256-
WriteNode exceptName = exceptNode.asName != null ? (WriteNode) scopeEnvironment.findVariable(exceptNode.asName).makeWriteNode(null) : null;
1257-
exceptNodes[i] = new ExceptNode(exceptBody, exceptTest, exceptName);
1267+
WriteNode exceptName = null;
1268+
StatementNode exceptNameDelete = null;
1269+
if (exceptNode.asName != null) {
1270+
ReadNode readAsNode = scopeEnvironment.findVariable(exceptNode.asName);
1271+
exceptName = (WriteNode) readAsNode.makeWriteNode(null);
1272+
exceptNameDelete = unbindVariable(readAsNode);
1273+
}
1274+
exceptNodes[i] = new ExceptNode(exceptBody, exceptTest, exceptName, exceptNameDelete);
12581275
}
12591276
PNode result = new TryFinallyNode(new TryExceptNode(body, exceptNodes, elseStatement), finalyStatement);
12601277
result.assignSourceSection(createSourceSection(node.startOffset, node.endOffset));

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/sst/GeneratorFactorySSTVisitor.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,14 @@ public PNode visit(TrySSTNode node) {
351351
ExceptSSTNode exceptNode = node.exceptNodes[i];
352352
ExpressionNode exceptTest = exceptNode.test != null ? (ExpressionNode) exceptNode.test.accept(this) : null;
353353
StatementNode exceptBody = (StatementNode) exceptNode.body.accept(this);
354-
WriteNode exceptName = exceptNode.asName != null ? (WriteNode) scopeEnvironment.findVariable(exceptNode.asName).makeWriteNode(null) : null;
355-
exceptNodes[i] = new ExceptNode(exceptBody, exceptTest, exceptName);
354+
WriteNode exceptName = null;
355+
StatementNode exceptNameDelete = null;
356+
if (exceptNode.asName != null) {
357+
ReadNode readAsNode = scopeEnvironment.findVariable(exceptNode.asName);
358+
exceptName = (WriteNode) readAsNode.makeWriteNode(null);
359+
exceptNameDelete = unbindVariable(readAsNode);
360+
}
361+
exceptNodes[i] = new ExceptNode(exceptBody, exceptTest, exceptName, exceptNameDelete);
356362
}
357363

358364
StatementNode result;

0 commit comments

Comments
 (0)