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;
}