private ExpressionInfo Node_MethodCall(XmlNode node) { var functionCallExtractor = new FunctionCallExtractor(); var methodCall = functionCallExtractor.ExtractMethodCall(node, this._variableStorage, this._analysisScope); bool isAlreadyInStack = _analysisStacks.CallStack.Any(x => x.Name == methodCall.Name); _analysisStacks.CallStack.Push(methodCall); var argInfos = new List<ExpressionInfo>(); //Actually analyze the arguments for (uint index = 1; index <= methodCall.Arguments.Count; index++) { var item = methodCall.Arguments.FirstOrDefault(x => x.Key == index); var exprInfo = this.Analyze(item.Value); if (_varResolver.IsResolvableNode(item.Value)) { var @var = _varResolver.ResolveVariable(item.Value); exprInfo.ValueInfo = @var.Variable.Info; } argInfos.Add(exprInfo); } if (methodCall.Name == "") { var exprInfo = new ExpressionInfo(); _analysisStacks.CallStack.Pop(); return argInfos.Aggregate(exprInfo, (current, info) => current.Merge(info)); } var customFunctionHandler = new CustomFunctionHandler(this._analyzer, _subroutineAnalyzerFactory); customFunctionHandler.AnalysisExtensions.AddRange(this.AnalysisExtensions); var functionMethodAnalyzer = _subroutineAnalyzerFactory.Create(ImmutableVariableStorage.CreateFromMutable(_variableStorage), _inclusionResolver, _analysisStacks, customFunctionHandler, _vulnerabilityStorage); var methodCallTaintSet = new ExpressionInfo(); if(!isAlreadyInStack) { methodCallTaintSet = functionMethodAnalyzer.AnalyzeMethodCall(methodCall, argInfos); } FunctionsHandler fh = FunctionsHandler.Instance; var resultTaintSet = new ExpressionInfo(); foreach (var className in methodCall.ClassNames.Distinct()) { var tempResultTaintSet = methodCallTaintSet.AssignmentClone(); var sqlSaniFunc = fh.FindSQLSanitizerByName(methodCall.CreateFullMethodName(className)); var sqlSinkFunc = fh.FindSQLSinkByName(methodCall.CreateFullMethodName(className)); var xssSaniFunc = fh.FindXSSSanitizerByName(methodCall.CreateFullMethodName(className)); var xssSinkFunc = fh.FindXSSSinkByName(methodCall.CreateFullMethodName(className)); if (sqlSaniFunc != null && sqlSaniFunc.DefaultStatus == SQLITaint.None) { resultTaintSet.ExpressionTaint.SqliTaint.Clear(); } if (xssSaniFunc != null && xssSaniFunc.DefaultStatus == XSSTaint.None) { resultTaintSet.ExpressionTaint.XssTaint.Clear(); } if (sqlSinkFunc != null || xssSinkFunc != null) { if (sqlSinkFunc != null) { var vulnerableSqlParams = sqlSinkFunc.Parameters.Where(x => x.Value.IsSensitive) .ToDictionary(pair => pair.Key); var parameters = methodCall.Arguments.Where(x => vulnerableSqlParams.Keys.Any(z => z.Item1 == x.Key)); foreach (var parameter in parameters) { //var argInfo = Analyze(parameter.Value); var argInfo = argInfos.ElementAt((int)(parameter.Key - 1)); CheckForSQLVulnerabilities(argInfo, parameter.Value); } if (sqlSinkFunc.ReturnType == "object" || sqlSinkFunc.ReturnType == "mix") { resultTaintSet.ValueInfo.ClassNames.AddRange(sqlSinkFunc.Classnames); } } if (xssSinkFunc != null) { var vulnerableXssParams = xssSinkFunc.Parameters.Where(x => x.Value.IsSensitive).ToDictionary(pair => pair.Key); var param = methodCall.Arguments.Where(x => vulnerableXssParams.Keys.Any(z => z.Item1 == x.Key)); foreach (var parameter in param) { var argInfo = argInfos.ElementAt((int)(parameter.Key - 1)); CheckForXssVulnerabilities(argInfo, parameter.Value); } } // Assuming sinks does not return taint. resultTaintSet.ExpressionTaint.ClearTaint(); resultTaintSet.ExpressionStoredTaint.Taint.ClearTaint(); } tempResultTaintSet = StoredMethodHandler(tempResultTaintSet, node); resultTaintSet = resultTaintSet.Merge(tempResultTaintSet); var methodNameWithClass = methodCall.CreateFullMethodName(className); bool isStoredProvider = FunctionsHandler.Instance.FindStoredProviderMethods(methodNameWithClass).Any(); if (isStoredProvider) { resultTaintSet.ExpressionStoredTaint = resultTaintSet.ExpressionStoredTaint.Merge(methodCall.Var.Info.PossibleStoredTaint); //TODO: The following is not true in all cases. // What cases? var cloned = resultTaintSet.ExpressionStoredTaint.Taint.DeepClone(); resultTaintSet.ValueInfo.NestedVariablePossibleStoredDefaultTaintFactory = () => cloned; } } _analysisStacks.CallStack.Pop(); return resultTaintSet; }