org.kohsuke.groovy.sandbox.ScopeTrackingClassCodeExpressionTransformer.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of groovy-sandbox Show documentation
Show all versions of groovy-sandbox Show documentation
Executes untrusted Groovy script safely
package org.kohsuke.groovy.sandbox
import org.codehaus.groovy.ast.ClassCodeExpressionTransformer
import org.codehaus.groovy.ast.MethodNode
import org.codehaus.groovy.ast.Parameter
import org.codehaus.groovy.ast.Variable
import org.codehaus.groovy.ast.expr.ClosureExpression
import org.codehaus.groovy.ast.expr.DeclarationExpression
import org.codehaus.groovy.ast.expr.Expression
import org.codehaus.groovy.ast.expr.TupleExpression
import org.codehaus.groovy.ast.expr.VariableExpression
import org.codehaus.groovy.ast.stmt.BlockStatement
import org.codehaus.groovy.ast.stmt.CatchStatement
import org.codehaus.groovy.ast.stmt.DoWhileStatement
import org.codehaus.groovy.ast.stmt.ForStatement
import org.codehaus.groovy.ast.stmt.IfStatement
import org.codehaus.groovy.ast.stmt.SwitchStatement
import org.codehaus.groovy.ast.stmt.SynchronizedStatement
import org.codehaus.groovy.ast.stmt.TryCatchStatement
import org.codehaus.groovy.ast.stmt.WhileStatement
/**
* Keeps track of in-scope variables.
*
* @author Kohsuke Kawaguchi
*/
abstract class ScopeTrackingClassCodeExpressionTransformer extends ClassCodeExpressionTransformer {
/**
* As we visit expressions, track variable scopes.
* This is used to distinguish local variables from property access. See issue #11.
*/
private StackVariableSet varScope;
public boolean isLocalVariable(String name) {
return varScope.has(name);
}
@Override
void visitMethod(MethodNode node) {
varScope = null;
withVarScope {
for (Parameter p : node.parameters) {
declareVariable(p)
}
super.visitMethod(node)
}
}
/**
* Evaluates the body in a new variable sccope.
*/
protected void withVarScope(Closure body) {
varScope = new StackVariableSet(varScope);
try {
body();
} finally {
varScope = varScope.parent;
}
}
@Override
void visitBlockStatement(BlockStatement block) {
withVarScope {
super.visitBlockStatement(block)
}
}
@Override
void visitDoWhileLoop(DoWhileStatement loop) {
withVarScope {
super.visitDoWhileLoop(loop)
}
}
@Override
void visitForLoop(ForStatement forLoop) {
withVarScope {
/*
Groovy appears to always treat the left-hand side of forLoop as a declaration.
i.e., the following code is error
def h() {
def x =0;
def i = 0;
for (i in 0..9 ) {
x+= i;
}
println x;
}
script1414457812466.groovy: 18: The current scope already contains a variable of the name i
@ line 18, column 5.
for (i in 0..9 ) {
^
1 error
Also see issue 17.
*/
declareVariable(forLoop.variable);
super.visitForLoop(forLoop)
}
}
@Override
void visitIfElse(IfStatement ifElse) {
withVarScope {
super.visitIfElse(ifElse)
}
}
@Override
void visitSwitch(SwitchStatement statement) {
withVarScope {
super.visitSwitch(statement)
}
}
@Override
void visitSynchronizedStatement(SynchronizedStatement sync) {
withVarScope {
super.visitSynchronizedStatement(sync)
}
}
@Override
void visitTryCatchFinally(TryCatchStatement statement) {
withVarScope {
super.visitTryCatchFinally(statement)
}
}
@Override
void visitCatchStatement(CatchStatement statement) {
withVarScope {
declareVariable(statement.variable);
super.visitCatchStatement(statement)
}
}
@Override
void visitWhileLoop(WhileStatement loop) {
withVarScope {
super.visitWhileLoop(loop)
}
}
@Override
void visitClosureExpression(ClosureExpression expression) {
withVarScope {
super.visitClosureExpression(expression)
}
}
/**
* @see org.codehaus.groovy.classgen.asm.BinaryExpressionHelper#evaluateEqual(org.codehaus.groovy.ast.expr.BinaryExpression, boolean)
*/
void handleDeclarations(DeclarationExpression exp) {
if (exp.leftExpression instanceof VariableExpression) {
declareVariable((VariableExpression)exp.leftExpression);
}
if (exp instanceof TupleExpression) {
TupleExpression te = (TupleExpression) exp;
for (Expression e : te.expressions) {
declareVariable((VariableExpression)e);
}
}
}
def declareVariable(Variable exp) {
varScope.declare(exp.name)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy