public static ImmutableDictionary <IParameterSymbol, SyntaxNode> GetOrComputeHazardousParameterUsages( IOperation topmostBlock, Compilation compilation, ISymbol owningSymbol, bool pessimisticAnalysis = true) { Debug.Assert(topmostBlock != null); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); ParameterValidationResultWithHazardousUsages GetOrComputeLocationAnalysisResultForInvokedMethod(IBlockOperation methodTopmostBlock, IMethodSymbol method) { // getOrComputeLocationAnalysisResultOpt = null, so we do interprocedural analysis only one level down. Debug.Assert(methodTopmostBlock != null); return(GetOrComputeResult(methodTopmostBlock, method, wellKnownTypeProvider, getOrComputeLocationAnalysisResultOpt: null, pessimisticAnalysis: pessimisticAnalysis)); }; ParameterValidationResultWithHazardousUsages result = GetOrComputeResult(topmostBlock, owningSymbol, wellKnownTypeProvider, GetOrComputeLocationAnalysisResultForInvokedMethod, pessimisticAnalysis); return(result.HazardousParameterUsages); }
public override ParameterValidationAbstractValue VisitArgumentCore(IArgumentOperation operation, object argument) { var value = base.VisitArgumentCore(operation, argument); // Arguments to validation methods must be marked as validated. var notValidatedLocations = GetNotValidatedLocations(operation); if (notValidatedLocations.Any()) { if (_getOrComputeLocationAnalysisResultOpt != null) { IMethodSymbol targetMethod = null; if (operation.Parent is IInvocationOperation invocation) { targetMethod = invocation.TargetMethod; } else if (operation.Parent is IObjectCreationOperation objectCreation) { targetMethod = objectCreation.Constructor; } if (targetMethod != null && targetMethod != OwningSymbol) { if (targetMethod.ContainingType.SpecialType == SpecialType.System_String) { if (targetMethod.IsStatic && targetMethod.Name.StartsWith("IsNull", StringComparison.Ordinal) && targetMethod.Parameters.Length == 1) { // string.IsNullOrXXX check. SetAbstractValue(notValidatedLocations, ParameterValidationAbstractValue.Validated); } } else if (WellKnownTypeProvider.Exception != null && targetMethod.ContainingType.DerivesFrom(WellKnownTypeProvider.Exception)) { // FxCop compat: special cases handled by FxCop. // 1. First argument of type System.Runtime.Serialization.SerializationInfo to System.Exception.GetObjectData or its override is validated. // 2. First argument of type System.Runtime.Serialization.SerializationInfo to constructor of System.Exception or its subtype is validated. if (operation.Parameter.Type == WellKnownTypeProvider.SerializationInfo) { switch (targetMethod.MethodKind) { case MethodKind.Ordinary: if (targetMethod.Name.Equals("GetObjectData", StringComparison.OrdinalIgnoreCase)) { SetAbstractValue(notValidatedLocations, ParameterValidationAbstractValue.Validated); } break; case MethodKind.Constructor: SetAbstractValue(notValidatedLocations, ParameterValidationAbstractValue.Validated); break; } } } else { var methodTopmostBlock = targetMethod.GetTopmostOperationBlock(WellKnownTypeProvider.Compilation); if (methodTopmostBlock != null) { ParameterValidationResultWithHazardousUsages invokedMethodAnalysisResult = _getOrComputeLocationAnalysisResultOpt(methodTopmostBlock, targetMethod); var invokedMethodLocationAnalysisResult = invokedMethodAnalysisResult.ParameterValidationAnalysisResult; var hazardousParameterUsagesInInvokedMethod = invokedMethodAnalysisResult.HazardousParameterUsages; if (invokedMethodLocationAnalysisResult != null) { Debug.Assert(hazardousParameterUsagesInInvokedMethod != null); // Non-validated argument passed to private/internal methods might be hazardous. if (hazardousParameterUsagesInInvokedMethod.ContainsKey(operation.Parameter)) { if (_hazardousParameterUsageBuilderOpt != null && !targetMethod.IsExternallyVisible()) { HandlePotentiallyHazardousOperation(operation, notValidatedLocations); } } else if (!targetMethod.IsVirtual && !targetMethod.IsOverride) { // Check if this is a non-virtual non-override method that validates the argument. BasicBlock invokedMethodExitBlock = invokedMethodLocationAnalysisResult.ControlFlowGraph.Exit; foreach (var kvp in invokedMethodLocationAnalysisResult[invokedMethodExitBlock].OutputData) { AbstractLocation parameterLocation = kvp.Key; ParameterValidationAbstractValue parameterValue = kvp.Value; Debug.Assert(parameterLocation.SymbolOpt is IParameterSymbol invokedMethodParameter && invokedMethodParameter.ContainingSymbol == targetMethod); // Check if the matching parameter was validated by the invoked method. if ((IParameterSymbol)parameterLocation.SymbolOpt == operation.Parameter && parameterValue == ParameterValidationAbstractValue.Validated) { SetAbstractValue(notValidatedLocations, ParameterValidationAbstractValue.Validated); break; } } } } } } } } } return(value); }