public MethodCall ExtractMethodCall(XmlNode node, IVariableStorage varStorage, AnalysisScope scope = AnalysisScope.File) { int startLine = AstNode.GetStartLine(node); int endLine = AstNode.GetEndLine(node); string methodName = ""; //Get the varNode which includes either (new ClassName())->MethodName or $var->MethodName var varNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var); var classNames = new List<string>(); if (varNode.FirstChild.LocalName == AstConstants.Nodes.Expr_New) { //PHP: (new ClassName(args))->MethodName(args); //Extract the ClassName directly, in this case there can be only one ClassName! var className = varNode.FirstChild .GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Class) .GetSubNode(AstConstants.Node + ":" + AstConstants.Nodes.Name) .GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Parts).FirstChild.FirstChild.InnerText; classNames.Add(className); methodName = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name).InnerText; return new MethodCall(methodName, classNames, node, startLine, endLine) { Arguments = ExtractArgumentNodes(node) }; } else { //PHP: $var->MethodName(args); //Resolve the variable, and get all the possible class names! VariableResolver vr = new VariableResolver(varStorage, scope); VariableResolveResult variableResult = null; if (vr.IsResolvableNode(varNode.FirstChild)) { variableResult = vr.ResolveVariable(varNode.FirstChild); classNames.AddRange(variableResult.Variable.Info.ClassNames.Where(className => !classNames.Contains(className))); } var nameSubnode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name); XmlNode nameNode = null; bool success = nameSubnode.TryGetSubNode(AstConstants.Node + ":" + AstConstants.Nodes.Name, out nameNode); if (success) { methodName = nameNode.InnerText; } else { if (nameSubnode.FirstChild.LocalName == AstConstants.Scalars.String) { methodName = nameSubnode.FirstChild.InnerText; } } return variableResult == null ? new MethodCall(methodName, classNames, node, startLine, endLine) { Arguments = ExtractArgumentNodes(node) } : new MethodCall(methodName, classNames, node, startLine, endLine, variableResult.Variable) { Arguments = ExtractArgumentNodes(node) }; } }
public static XmlNode GetCondNode(XmlNode node) { Preconditions.NotNull(node, "node"); Preconditions.IsTrue(NodesWithCondSubNode.Contains(node.LocalName), "Expected node representing conditional statement. Received a " + node.Name); return node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Cond); }
public static string GetStringValue(XmlNode node) { Preconditions.NotNull(node, "node"); Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_String, "String value retrieval only supported for " + AstConstants.Nodes.Scalar_String + " nodes. Was " + node.Name, "node"); return node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value) .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.String).InnerText; }
public static int GetLValue(XmlNode node) { Preconditions.NotNull(node, "node"); Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_LNumber, "LValue retrieval only supported for " + AstConstants.Nodes.Scalar_LNumber + " nodes. Was " + node.Name, "node"); var innerText = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value) .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Int).InnerText; return int.Parse(innerText); }
public static double GetDValue(XmlNode node) { Preconditions.NotNull(node, "Node"); Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_DNumber, "DValue retrieval only supported for " + AstConstants.Nodes.Scalar_DNumber + " nodes. Was " + node.Name, "node"); var innerText = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value) .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Float).InnerText; return double.Parse(innerText, CultureInfo.InvariantCulture); }
public static IEnumerable<XmlNode> GetVariables(XmlNode node) { Preconditions.NotNull(node, "node"); Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Stmt_Global, "Node has to be a global statement. It was: " + node.Name, "node"); var variables = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Vars) .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Array) .GetSubnodes(AstConstants.Node + ":" + AstConstants.Nodes.Expr_Variable); return variables; }
public FunctionCall ExtractFunctionCall(XmlNode node) { int startLine = AstNode.GetStartLine(node); int endLine = AstNode.GetEndLine(node); string funcName = ""; XmlNode nameSubNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name); XmlNode nameNode = null; bool success = nameSubNode.TryGetSubNode(AstConstants.Node + ":" + AstConstants.Nodes.Name, out nameNode); if (success) { funcName = nameNode.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Parts).InnerText; } return new FunctionCall(funcName, node, startLine, endLine) { Arguments = ExtractArgumentNodes(node) }; }
/// <summary> /// Tries to get the variables name. This will only work if the variable name is static. /// <example>$var : will be 'var'</example> /// <example>$$var : will fail.</example> /// </summary> public static bool TryGetVariableName(XmlNode node, out string varName) { Preconditions.NotNull(node, "node"); Preconditions.IsTrue(node.Name == AstConstants.Node + ":" + AstConstants.Nodes.Expr_Variable, "Node has to be an Expression Variable. It was: " + node.Name, "node"); var nameNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Name); if (nameNode.TryGetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.String, out nameNode)) { varName = nameNode.InnerText; return true; } varName = null; return false; }
private ExpressionInfo Node_Expr_Assign(XmlNode node) { var rhsExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); var rhsTaint = Analyze(rhsExpr); var lhsExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var); Variable variable; if (_varResolver.IsResolvableNode(lhsExpr.FirstChild)) { variable = _varResolver.ResolveVariable(lhsExpr.FirstChild).Variable; } else { // LHS of assignment is not necessarily something we support. E.g. list(..,..) = ... // In that case we use a "dummy" variable variable = new Variable("$UNKNOWN$", _analysisScope.ToVariableScope()); } var rhsExprNodes = rhsExpr.GetSubNodesByPrefix(AstConstants.Node); if (rhsExprNodes.Any()) { var rhsExprNode = rhsExprNodes.Single(); if (_varResolver.IsResolvableNode(rhsExprNode)) { // If simple var to var assignment, move relevant var info to lhs variabel var rhsVariable = _varResolver.ResolveVariable(rhsExprNode).Variable; variable.Info = rhsVariable.Info.AssignmentClone(); return rhsTaint; } if (rhsTaint.ValueInfo.Value != null) { variable.Info.Value = rhsTaint.ValueInfo.Value; variable.Info.Type = rhsTaint.ValueInfo.Type; variable.Info.ClassNames.AddRange(rhsTaint.ValueInfo.ClassNames); } } variable.Info = variable.Info.Merge(rhsTaint.ValueInfo); if (rhsTaint.ValueInfo.Equals(new ValueInfo())) // HACK - Hacky way of determining if it hasn't been changed. { variable.Info.Taints = rhsTaint.ExpressionTaint; variable.Info.PossibleStoredTaint = rhsTaint.ExpressionStoredTaint; variable.Info.Type = rhsTaint.ValueInfo.Type; variable.Info.ClassNames.AddRange(rhsTaint.ValueInfo.ClassNames); return rhsTaint; } variable.Info = rhsTaint.ValueInfo.AssignmentClone(); return rhsTaint; }
private ExpressionInfo Node_Echo(XmlNode node) { var taintResult = Analyze(node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Exprs)); CheckForXssVulnerabilities(taintResult, node); return new ExpressionInfo(); }
private ExpressionInfo Expr_UnaryOp_AlwaysSafe(XmlNode node) { var expr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); Analyze(expr); return new ExpressionInfo(); }
private ExpressionInfo Expr_Include(XmlNode node) { var inclExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); Analyze(inclExpr); File file; if (_inclusionResolver.TryResolveInclude(node, out file)) { if (!_analysisStacks.IncludeStack.Contains(file)) { Console.WriteLine(">> Resolved " + file.Name + ". Starting analysis."); _analysisStacks.IncludeStack.Push(file); var result = _analyzer(ImmutableVariableStorage.CreateFromMutable(_variableStorage), _inclusionResolver, _analysisScope, _analysisStacks); this._variableStorage = result.Merge(ImmutableVariableStorage.CreateFromMutable(this._variableStorage)).ToMutable(); _analysisStacks.IncludeStack.Pop(); Console.WriteLine(">> Finished " + file.Name + ". Continuing."); } } return new ExpressionInfo(); }
private ExpressionInfo Expr_Exit(XmlNode node) { var exprNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); var expressionTaint = Analyze(exprNode); CheckForXssVulnerabilities(expressionTaint, node); return new ExpressionInfo(); }
private ExpressionInfo Expr_BinaryOp_NonSpecial_AlwaysSafe(XmlNode node) { XmlNode leftExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Left); Analyze(leftExpr); XmlNode rightExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Right); Analyze(rightExpr); return new ExpressionInfo(); }
private ExpressionInfo Scalar_Encapsed(XmlNode node) { var partsArray = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Parts) .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Array); var encapsedParts = partsArray.GetSubNodesByPrefixes(AstConstants.Node, AstConstants.Scalar); var result = new ExpressionInfo(); foreach (var partResult in encapsedParts.Select(Analyze)) { result.ExpressionTaint = result.ExpressionTaint.Merge(partResult.ExpressionTaint); result.ValueInfo.Value = result.ValueInfo.Value + partResult.ValueInfo.Value; } return result; }
private ExpressionInfo Expr_BinaryOp_BooleanOperator(XmlNode node) { var left = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Left); var right = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Right); Analyze(left); Analyze(right); return new ExpressionInfo(); }
private ExpressionInfo Expr_BinaryOp_Concat(XmlNode node) { XmlNode leftExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Left) .GetSubNodesByPrefix(AstConstants.Node).Single(); XmlNode rightExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Right) .GetSubNodesByPrefix(AstConstants.Node).Single(); var leftResult = Analyze(leftExpr); var rightResult = Analyze(rightExpr); var result = leftResult.Merge(rightResult); if (leftResult.ValueInfo.Value != null && rightResult.ValueInfo.Value != null) { result.ValueInfo.Value = leftResult.ValueInfo.Value + rightResult.ValueInfo.Value; } return result; }
private ExpressionInfo Stmt_Foreach(XmlNode node) { var expr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); var keyVar = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.KeyVar); var byRef = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.ByRef); var valueVar = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.ValueVar); var exprResult = Analyze(expr); var keyVarResult = Analyze(keyVar); var valueVarResult = Analyze(valueVar); var exprNode = expr.GetSubNodesByPrefix(AstConstants.Node).Single(); Variable exprVariable = new Variable("$UNKNOWN var$ - Just here to prevent null checks.", _analysisScope.ToVariableScope()); if (_varResolver.IsResolvableNode(exprNode)) { exprVariable = _varResolver.ResolveVariable(exprNode).Variable; } var defaultKeyTaint = exprResult.ValueInfo.DefaultDimensionTaintFactory(); var defaultValuePossibleTaint = exprResult.ValueInfo.NestedVariablePossibleStoredDefaultTaintFactory(); var defaultValueTaint = exprResult.ValueInfo.NestedVariableDefaultTaintFactory(); var keyNode = keyVar.GetSubNodesByPrefix(AstConstants.Node).SingleOrDefault(); // Might be a scalar! if (keyNode != null && this._varResolver.IsResolvableNode(keyNode)) { var varResolveResult = _varResolver.ResolveVariable(keyNode); varResolveResult.Variable.Info.Taints = varResolveResult.Variable.Info.Taints.Merge(defaultKeyTaint); } var variableTaints = exprResult.ValueInfo.Variables.Select(x => x.Value.Info.Taints).ToList(); TaintSets worstVariableTaint = variableTaints.Any() ? variableTaints.Aggregate((current, next) => current.Merge(next)) : defaultValueTaint; worstVariableTaint = worstVariableTaint.Merge(defaultValueTaint); var variablePossibleTaint = exprResult.ValueInfo.Variables.Select(x => x.Value.Info.PossibleStoredTaint.Taint).ToList(); TaintSets worstVariablePossibleTaint = variablePossibleTaint.Any() ? variablePossibleTaint.Aggregate((current, next) => current.Merge(next)) : defaultValuePossibleTaint; worstVariablePossibleTaint = worstVariablePossibleTaint.Merge(defaultValuePossibleTaint); var valueNode = valueVar.GetSubNodesByPrefix(AstConstants.Node).Single(); if (this._varResolver.IsResolvableNode(valueNode)) { var varResolveResult = _varResolver.ResolveVariable(valueNode).Variable; varResolveResult.Info.Taints = varResolveResult.Info.Taints.Merge(worstVariableTaint); varResolveResult.Info.Taints = varResolveResult.Info.Taints.Merge(exprVariable.Unknown.Info.Taints); varResolveResult.Info.PossibleStoredTaint = _varResolver.ClonePossibleStored(exprVariable.Info); varResolveResult.Info.PossibleStoredTaint.Taint = varResolveResult.Info.PossibleStoredTaint.Taint.Merge(worstVariablePossibleTaint); varResolveResult.Info.PossibleStoredTaint.Taint = varResolveResult.Info.PossibleStoredTaint.Taint.Merge(exprVariable.Unknown.Info.PossibleStoredTaint.Taint); varResolveResult.Info.NestedVariablePossibleStoredDefaultTaintFactory = exprResult.ValueInfo.NestedVariablePossibleStoredDefaultTaintFactory; varResolveResult.Info.NestedVariableDefaultTaintFactory = exprResult.ValueInfo.NestedVariableDefaultTaintFactory; } return new ExpressionInfo(); }
private ExpressionInfo Expr_BooleanNot(XmlNode node) { var result = Analyze(node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr)); return result; }
private ExpressionInfo Stmt_Return(XmlNode node) { var exprNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); ExpressionInfo exprInfo = Analyze(exprNode); this.ReturnInfos.Add(exprInfo); return new ExpressionInfo(); }
private ExpressionInfo Expr_IncDec(XmlNode node) { var varNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var); Analyze(varNode); varNode = varNode.GetSubNodesByPrefix(AstConstants.Node).Single(); VariableResolveResult variabel = _varResolver.ResolveVariable(varNode); return new ExpressionInfo() { ExpressionTaint = variabel.Variable.Info.Taints }; }
private ExpressionInfo Subnode_Exprs(XmlNode node) { var arraynode = node.GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Array); var subnodes = arraynode.GetSubNodesByPrefix(AstConstants.Node); var results = new ExpressionInfo(); var temptaintsets = subnodes.Select(Analyze).ToList(); return temptaintsets.Aggregate(results, (current, exprTaint) => current.Merge(exprTaint)); }
private ExpressionInfo Expr_Ternary(XmlNode node) { var condNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Cond); var ifTrueNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.If); var ifFalseNode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Else); Analyze(condNode); var condAnalyzer = new ConditionTaintAnalyser(_analysisScope, this._inclusionResolver, _analysisStacks.IncludeStack); var condResult = condAnalyzer.AnalyzeCond(condNode, ImmutableVariableStorage.CreateFromMutable(_variableStorage)); var currentResolver = this._varResolver; this._varResolver = new VariableResolver(condResult[EdgeType.True].ToMutable()); var leftTaint = Analyze(ifTrueNode); this._varResolver = new VariableResolver(condResult[EdgeType.False].ToMutable()); var rightTaint = Analyze(ifFalseNode); this._varResolver = currentResolver; return leftTaint.Merge(rightTaint); }
private ExpressionInfo Subnode_Init(XmlNode node) { var initExpressions = node .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Array) .GetSubNodesByPrefix(AstConstants.Node); foreach (var initExpression in initExpressions) { Analyze(initExpression); } return new ExpressionInfo(); }
private Tuple<VariableTreeDimension, ValueInfo> Handle_Expr_ArrayItem(XmlNode node) { VariableTreeDimension arrayKey; var itemInfo = new ValueInfo(); var valueResult = Analyze(node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Value)); itemInfo.Taints = valueResult.ExpressionTaint; if (valueResult.ValueInfo != null) { itemInfo = valueResult.ValueInfo.AssignmentClone(); } var dimension = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Key); Analyze(dimension); // Start dimension resolving - This should probably be refactored! var dimNode = dimension.GetSubNodesByPrefix(AstConstants.Node).SingleOrDefault(); // Rules: // Strings with valid integers are cast // Floats are cast to integer (fraction is truncated) // Bools are cast to integers (true = 1, false = 0) // Null = empty string // Arrays/Objects cannot be used as key. // // Conflict - Last one wins. if (dimNode == null) { arrayKey = new VariableTreeDimension() { Index = -1, Key = "$UKENDT$" }; } else { if (dimNode.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_String) { var stringValue = ScalarNode.GetStringValue(dimNode); arrayKey = new VariableTreeDimension() { Key = stringValue }; double indexValue; if (double.TryParse(stringValue, out indexValue)) { arrayKey.Index = (int)indexValue; } } else if (dimNode.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_LNumber) { var index = ScalarNode.GetLValue(dimNode); arrayKey = new VariableTreeDimension() { Index = index, Key = index.ToString(CultureInfo.InvariantCulture) }; } else if (dimNode.Name == AstConstants.Node + ":" + AstConstants.Nodes.Scalar_DNumber) { var index = (int)ScalarNode.GetDValue(dimNode); arrayKey = new VariableTreeDimension() { Index = index, Key = index.ToString(CultureInfo.InvariantCulture) }; } else { // Default case. ie. Non resolvable dimension arrayKey = new VariableTreeDimension() { Index = -1, Key = "$UKENDT$" }; } } // End dimension resolving. return new Tuple<VariableTreeDimension, ValueInfo>(arrayKey, itemInfo); }
private ExpressionInfo Expr_Array(XmlNode node) { var arrayItems = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Items) .GetSubNode(AstConstants.Scalar + ":" + AstConstants.Scalars.Array) .GetSubnodes(AstConstants.Node + ":" + AstConstants.Nodes.Expr_ArrayItem); var varInfo = new ValueInfo(); foreach (var arrayItem in arrayItems) { var info = Handle_Expr_ArrayItem(arrayItem); var arrayVar = new Variable(info.Item1.ToString(), VariableScope.Instance) { Info = info.Item2 }; varInfo.Variables[info.Item1] = arrayVar; } return new ExpressionInfo() { ExpressionTaint = new TaintSets(), ValueInfo = varInfo }; }
private ExpressionInfo Node_Expr_ArrayDimFetch(XmlNode node) { var varSubnode = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var); Analyze(varSubnode); var variabel = _varResolver.ResolveVariable(node).Variable; variabel.Info.Taints.XssTaint.ForEach(x => x.InitialTaintedVariable = variabel.Name); variabel.Info.Taints.SqliTaint.ForEach(x => x.InitialTaintedVariable = variabel.Name); variabel.Info.PossibleStoredTaint.Taint.XssTaint.ForEach(x => x.InitialTaintedVariable = variabel.Name); variabel.Info.PossibleStoredTaint.Taint.SqliTaint.ForEach(x => x.InitialTaintedVariable = variabel.Name); return new ExpressionInfo() { ExpressionTaint = variabel.Info.Taints, ValueInfo = variabel.Info.AssignmentClone() }; }
private ExpressionInfo Expr_AssignOp_Concat(XmlNode node) { var rhsExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); var rhsTaint = Analyze(rhsExpr); var lhsExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var); var lhsVariable = _varResolver.ResolveVariable(lhsExpr.FirstChild).Variable; lhsVariable.Info.Taints = lhsVariable.Info.Taints.Merge(rhsTaint.ExpressionTaint); var result = new ExpressionInfo() { ExpressionTaint = lhsVariable.Info.Taints }; if (lhsVariable.Info.Value != null && rhsTaint.ValueInfo.Value != null) { lhsVariable.Info.Value = lhsVariable.Info.Value + rhsTaint.ValueInfo.Value; } return result; }
private ExpressionInfo Node_Expr_Cast(XmlNode node) { var subExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); var subExprTaint = Analyze(subExpr); var sanitizationCasts = new[] { AstConstants.Nodes.Expr_Cast_Unset, AstConstants.Nodes.Expr_Cast_Bool, AstConstants.Nodes.Expr_Cast_Double, AstConstants.Nodes.Expr_Cast_Int, }; if (sanitizationCasts.Contains(node.LocalName)) { return new ExpressionInfo(); } return subExprTaint; }
private ExpressionInfo Expr_AssignOp_NonSpecial_AlwaysSafe(XmlNode node) { var rhsExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr); Analyze(rhsExpr); var lhsExpr = node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Var); var variable = _varResolver.ResolveVariable(lhsExpr.FirstChild); variable.Variable.Info.Taints = new TaintSets().ClearTaint(); return new ExpressionInfo(); }