private void Handle(MethodCallEffect methodCall, ExecutionContext executionContext) { executionContext.MethodCallCount++; result.Stat.MethodCallCount++; if (methodCall.Signature == taintedCall) { if (!inputTaintedMode || methodCall.Parameters.Any(slot => slot.IsInput())) { // mark returned values as tainted // TODO: ref counter for tainted obj Debug.Assert(methodCall.OutputSlots.Count == 1, "for current tainted call this value always 1. Need to test other cases."); for (var i = 0; i < methodCall.OutputSlots.Count; i++) { var(id, backwardCallStack) = result.AddTaintedMethodCall(methodCall.Signature, CallStack); methodCall.OutputSlots[i].MarkTaint(id, backwardCallStack); } } else if (inputTaintedMode) { for (int i = 0; i < methodCall.Parameters.Length; i++) { var parameter = methodCall.Parameters[i]; parameter.AddSinkMethod(executionContext.Signature, CallStack, methodCall.OutputSlots); } } result.Stat.IgnoredTargetMethodCalls++; return; } var isAnalyzing = IsAnalyzingNeeded(methodCall); AddTargetMethodIfNeeded(methodCall, isAnalyzing); if (!isAnalyzing) { return; } var summary = GetOrCreateSummary(methodCall); executionContext.Apply(summary, methodCall.Parameters, result, ReturnValueApplyingMode.Replace, Indent()); }
private bool IsAnalyzingNeeded(MethodCallEffect methodCall) { // probably we can cache 'empty' (with Input marks if needed) summary for non-analyzing cases // to improve performance (need to benchmark it) if (methodCall.Definition == null) { DebugLog($"{Indent()}{methodCall.Signature}: MethodDefinition == null"); MarkOutputSlotsAsInput(methodCall); result.Stat.IgnoredNotImplementedMethodCalls++; return(false); } if (methodCall.CallKind == CallKind.Concrete && !methodCall.Definition.HasBody) { DebugLog($"{Indent()}{methodCall.Signature}: no body"); MarkOutputSlotsAsInput(methodCall); if (methodCall.Definition.HasReturnType) { var returnType = methodCall.Definition.ReturnType.TryGetTypeDef(); if (returnType != null) { // register types from external methods and delegates RegisterType(returnType); } } result.Stat.IgnoredNotImplementedMethodCalls++; return(false); } if (methodCall.CallKind == CallKind.Virtual) { int implMethodsCount; var registeredTypes = GetRegisteredTypes(methodCall.Definition.DeclaringType.ScopeType.ToString()); if (registeredTypes.Count == 0) { DebugLog($"{Indent()}{methodCall.Signature}: no created types"); //Console.WriteLine($"{methodCall.Signature}: no created types"); MarkOutputSlotsAsInput(methodCall); result.Stat.IgnoredNotImplementedMethodCalls++; // TODO: use another stat counter return(false); implMethodsCount = indexDb.GetImplementationsCount(methodCall.Signature); //, entryPointAssemblyName); } else { implMethodsCount = indexDb.GetImplementationsCount(methodCall.Signature, registeredTypes); } if (!methodCall.Definition.HasBody && implMethodsCount == 0) { DebugLog($"{Indent()}{methodCall.Signature}: no any implementation"); //Console.WriteLine($"{Indent()}{methodCall.Signature}: no any implementation"); MarkOutputSlotsAsInput(methodCall); result.Stat.IgnoredNotImplementedMethodCalls++; return(false); } if (implMethodsCount > virtualCallsLimit) //|| (registeredTypes.Count == 0 && implMethodsCount > 4)) { // TODO: need to propagate tainted value as well? //Console.WriteLine($"{methodCall.Signature}: too much implementations ({implMethodsCount})"); MarkOutputSlotsAsInput(methodCall); result.Stat.IgnoredVirtualMethodCallsByLimit++; result.Stat.IgnoredVirtualMethodsByLimit.Add(methodCall.Signature.ToString()); return(false); } } if (indexDb.SkippedModules.Contains(methodCall.Definition.Module.FullName)) { Console.WriteLine($"{methodCall.Signature}: in the skipped modules"); MarkOutputSlotsAsInput(methodCall); result.Stat.IgnoredNotImplementedMethodCalls++; return(false); } return(true); }
private void AddTargetMethodIfNeeded(MethodCallEffect methodCall, bool isAnalyzing) { if (methodCall.Parameters.Length == 0) { return; } /////////////////////////////////////////////////////// // TODO: ADD support for Delegate Invoke() call /* * if ((methodCall.IsVirtual && methodCall.Definition.IsVirtual) || * (methodCall.Definition == null || !methodCall.Definition.HasBody ||methodCall.Definition.Name == "SideEffect") && * list.IsValid(methodCall.Signature)) * { * for (int i = 0; i < methodCall.Parameters.Length; i++) * { * var parameter = methodCall.Parameters[i]; * parameter.AddTargetMethod(methodCall.Signature, result); * } * } * * return; */ /////////////////////////////////////////////////////// if (!isAnalyzing) { AddTargetMethodForAllParameters(methodCall); } else if (methodCall.Definition != null && methodCall.CallKind == CallKind.Virtual && methodCall.Definition.IsVirtual) { var implMethodsCount = indexDb.GetImplementationsCount(methodCall.Signature, entryPointAssemblyName); // add target methods only if we have several implementation if ((methodCall.Definition.HasBody && implMethodsCount > 0) || (!methodCall.Definition.HasBody && implMethodsCount > 1)) { methodCall.Parameters[0].AddTargetMethod(methodCall.Signature, CallStack, result); } } else if (methodCall.Definition == null || !methodCall.Definition.HasBody || methodCall.Definition.Name == "SideEffect") { AddTargetMethodForAllParameters(methodCall); } void AddTargetMethodForAllParameters(MethodCallEffect methodCallEffect) { if (list.IsValid(methodCallEffect.Signature)) { // TODO: need to exclude 'out' params, but leave 'ref' for (int i = 0; i < methodCallEffect.Parameters.Length; i++) { var parameter = methodCallEffect.Parameters[i]; parameter.AddTargetMethod(methodCallEffect.Signature, CallStack, result); } } } }