private static bool MatchesParameter(ISymbol symbol, IObjectCreationOperation creation, string stringArgumentValue) { if (MatchesParameterCore(symbol, stringArgumentValue)) { return(true); } var operation = creation.Parent; while (operation != null) { symbol = null; switch (operation.Kind) { case OperationKind.LocalFunction: symbol = ((ILocalFunctionOperation)operation).Symbol; break; case OperationKind.AnonymousFunction: symbol = ((IAnonymousFunctionOperation)operation).Symbol; break; } if (symbol != null && MatchesParameterCore(symbol, stringArgumentValue)) { return(true); } operation = operation.Parent; } return(false); }
private static Diagnostic?CheckArgument( ISymbol targetSymbol, IObjectCreationOperation creation, IParameterSymbol parameter, string stringArgument, OperationAnalysisContext context) { bool matchesParameter = MatchesParameter(targetSymbol, creation, stringArgument); if (IsMessage(parameter) && matchesParameter) { var dictBuilder = ImmutableDictionary.CreateBuilder <string, string?>(); dictBuilder.Add(MessagePosition, parameter.Ordinal.ToString(CultureInfo.InvariantCulture)); return(context.Operation.CreateDiagnostic(RuleIncorrectMessage, dictBuilder.ToImmutable(), targetSymbol.Name, stringArgument, parameter.Name, creation.Type.Name)); } else if (HasParameters(targetSymbol) && IsParameterName(parameter) && !matchesParameter) { // Allow argument exceptions in accessors to use the associated property symbol name. if (!MatchesAssociatedSymbol(targetSymbol, stringArgument)) { return(context.Operation.CreateDiagnostic(RuleIncorrectParameterName, targetSymbol.Name, stringArgument, parameter.Name, creation.Type.Name)); } } return(null); }
public override ParameterValidationAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) { var value = base.VisitObjectCreation(operation, argument); ProcessRegularInvocationOrCreation(operation.Constructor, operation.Arguments, operation); return(value); }
private void AnalyzeObjectCreationInternal(OperationAnalysisContext context, ISymbol variable, IOperation valueOpt) { IObjectCreationOperation objCreation = valueOpt as IObjectCreationOperation; if (objCreation == null) { return; } if (_objectCreationOperationsAnalyzed.Contains(objCreation)) { return; } else { _objectCreationOperationsAnalyzed.Add(objCreation); } if (SecurityDiagnosticHelpers.IsXmlDocumentCtorDerived(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlDocument(context, variable, objCreation); } else if (SecurityDiagnosticHelpers.IsXmlTextReaderCtorDerived(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlTextReader(context, variable, objCreation); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsCtor(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlReaderSettings(context, variable, objCreation); } else { AnalyzeMethodOverloads(context, objCreation.Constructor, objCreation.Arguments, objCreation.Syntax); } }
public override void VisitObjectCreation(IObjectCreationOperation operation) { Assert.Equal(OperationKind.ObjectCreation, operation.Kind); var constructor = operation.Constructor; // When parameter-less struct constructor is inaccessible, the constructor symbol is null if (!operation.Type.IsValueType) { Assert.NotNull(constructor); if (constructor == null) { Assert.Empty(operation.Arguments); } } IEnumerable <IOperation> children = operation.Arguments; if (operation.Initializer != null) { children = children.Concat(new[] { operation.Initializer }); } AssertEx.Equal(children, operation.Children); }
private static void CheckArgument( ISymbol targetSymbol, IObjectCreationOperation creation, IParameterSymbol parameter, string stringArgument, OperationAnalysisContext context) { bool matchesParameter = MatchesParameter(targetSymbol, creation, stringArgument); LocalizableString format = null; if (IsMessage(parameter) && matchesParameter) { format = s_localizableMessageIncorrectMessage; } else if (IsParameterName(parameter) && !matchesParameter) { // Allow argument exceptions in accessors to use the associated property symbol name. if (MatchesAssociatedSymbol(targetSymbol, stringArgument)) { return; } format = s_localizableMessageIncorrectParameterName; } if (format != null) { ReportDiagnostic(context, format, targetSymbol.Name, stringArgument, parameter.Name, creation.Type.Name); } }
public static void RegisterMemberAccess(this AnalysisContext context, Action <InvocationAnalysisContext> action) { var operationKinds = new[] { OperationKind.Invocation, OperationKind.SimpleAssignment, OperationKind.VariableDeclaration, OperationKind.ObjectCreation, OperationKind.FieldInitializer, OperationKind.FieldReference, }; context.RegisterOperationAction(ctx => { ISymbol?symbol = ctx.Operation switch { IInvocationOperation invocation => invocation.TargetMethod, IPropertyReferenceOperation property => property.Property.Type, IObjectCreationOperation creation => creation.Type, ISimpleAssignmentOperation assignment => assignment.Type, IFieldInitializerOperation fieldInitializer => fieldInitializer.Type, IFieldReferenceOperation fieldRef => fieldRef.Type, IVariableDeclarationOperation variableDeclaration => variableDeclaration.Type, _ => null, }; if (symbol is null) { return; } var location = ctx.Operation.Syntax.GetLocation(); var newCtx = new InvocationAnalysisContext(symbol, location, ctx.Compilation, ctx.Options, ctx.ReportDiagnostic, ctx.CancellationToken); action(newCtx); }, operationKinds); context.RegisterSymbolAction(ctx => { var symbol = ctx.Symbol switch { IPropertySymbol property => property.Type, IParameterSymbol parameter => parameter.Type, IMethodSymbol method => method.ReturnsVoid ? null : method.ReturnType, IFieldSymbol field => field.Type, _ => null, }; if (symbol is null) { return; } var location = ctx.Symbol.Locations[0]; var newCtx = new InvocationAnalysisContext(symbol, location, ctx.Compilation, ctx.Options, ctx.ReportDiagnostic, ctx.CancellationToken); action(newCtx); }, SymbolKind.Property, SymbolKind.Method, SymbolKind.Parameter, SymbolKind.Field); }
internal static Location GetExceptionalLocation(this IObjectCreationOperation @this) { if (@this.Syntax is ObjectCreationExpressionSyntax creationSyntax) { return(creationSyntax.Type.GetLocation()); } else { return(@this.Syntax.GetLocation()); } }
public override Scope VisitObjectCreation(IObjectCreationOperation operation, Scope currentScope) { var scope = currentScope; foreach (var argument in operation.Arguments) { scope = argument.Accept(this, scope); } return(scope); }
// So we can hook into constructor calls. public override TaintedDataAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) { TaintedDataAbstractValue baseValue = base.VisitObjectCreation(operation, argument); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(operation.Arguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(operation.Constructor, taintedArguments, operation); } return(baseValue); }
private void AnalyzeOperation(OperationAnalysisContext context) { var symbol = context.Operation switch { IObjectCreationOperation creation => creation.Constructor, IInvocationOperation invocation => invocation.TargetMethod, IFieldReferenceOperation field => field.Member, IMethodReferenceOperation method => method.Member, IPropertyReferenceOperation property => property.Member, IEventReferenceOperation @event => @event.Member, _ => throw new InvalidOperationException("Unexpected operation kind: " + context.Operation.Kind), }; VisitOperationSymbol(context, symbol); }
private static AbstractExpression ReadObjectCreation(IObjectCreationOperation op) { var context = CodeReaderContext.GetContextOrThrow(); var objectType = context.CodeModel.Get <TypeMember>(op.Type); var initializer = ReadExpression(op.Initializer); return(new NewObjectExpression { Type = objectType, ConstructorCall = new MethodCallExpression { Type = objectType, Method = context.CodeModel.Get <ConstructorMember>(op.Constructor), Arguments = op.Arguments.Select(ReadArgument).ToList() }, ObjectInitializer = initializer as ObjectInitializerExpression, CollectionInitializer = initializer as CollectionInitializerExpression }); }
private ISymbol?GetUnoSymbolFromOperation(IOperation operation) { ISymbol symbol = operation switch { IInvocationOperation invocationOperation => invocationOperation.TargetMethod, IObjectCreationOperation objectCreation => objectCreation.Type, IFieldReferenceOperation fieldReferenceOperation => fieldReferenceOperation.Field, IPropertyReferenceOperation propertyReferenceOperation => propertyReferenceOperation.Property, _ => throw new InvalidOperationException("This code path is unreachable.") }; if (IsUnoSymbol(symbol)) { return(symbol); } return(null); }
bool IsViolatingCodeActionObjectCreation(IObjectCreationOperation objectCreation) { return(objectCreation.Constructor.ContainingType.GetBaseTypesAndThis().All(namedType => !IsCodeActionWithOverriddenEquivalenceKey(namedType))); // Local functions bool IsCodeActionWithOverriddenEquivalenceKey(INamedTypeSymbol namedType) { if (namedType == null || namedType.Equals(_codeActionSymbol)) { return(false); } // We are already tracking CodeActions with equivalence key in this compilation. if (namedType.ContainingAssembly.Equals(_sourceAssembly)) { return(_codeActionsWithEquivalenceKey != null && _codeActionsWithEquivalenceKey.Contains(namedType)); } // For types in different compilation, perfom the check. return(IsCodeActionWithOverriddenEquivlanceKeyCore(namedType)); } }
private static void CheckArgument( ISymbol targetSymbol, IObjectCreationOperation creation, IParameterSymbol parameter, string stringArgument, OperationAnalysisContext context) { bool matchesParameter = MatchesParameter(targetSymbol, creation, stringArgument); LocalizableString format = null; if (IsMessage(parameter) && matchesParameter) { format = s_localizableMessageIncorrectMessage; } else if (IsParameterName(parameter) && !matchesParameter) { format = s_localizableMessageIncorrectParameterName; } if (format != null) { ReportDiagnostic(context, format, targetSymbol.Name, stringArgument, parameter.Name, creation.Type.Name); } }
private static async Task <Document> AddNullMessageToArgumentListAsync(Document document, IObjectCreationOperation creation, CancellationToken token) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, token).ConfigureAwait(false); SyntaxNode argument = AddNameOfIfLiteral(creation.Arguments[0].Value, editor.Generator); SyntaxNode newCreation = editor.Generator.ObjectCreationExpression(creation.Type, editor.Generator.Argument(editor.Generator.NullLiteralExpression()), argument); editor.ReplaceNode(creation.Syntax, newCreation); return(editor.GetChangedDocument()); }
public override ValueContentAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) { // TODO: Analyze string constructor // https://github.com/dotnet/roslyn-analyzers/issues/1547 return(base.VisitObjectCreation(operation, argument)); }
public sealed override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { Compilation?compilation = compilationStartAnalysisContext.Compilation; WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemDataDataSet, out INamedTypeSymbol? dataSetTypeSymbol) || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemDataDataTable, out INamedTypeSymbol? dataTableTypeSymbol)) { return; } INamedTypeSymbol?dataContractSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemRuntimeSerializationDataContractSerializer); INamedTypeSymbol?dataContractJsonSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemRuntimeSerializationJsonDataContractJsonSerializer); INamedTypeSymbol?javaScriptSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemWebScriptSerializationJavaScriptSerializer); INamedTypeSymbol?typeTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemType); INamedTypeSymbol?xmlSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemXmlSerializationXmlSerializer); INamedTypeSymbol?jsonNetJsonSerializerTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName( WellKnownTypeNames.NewtonsoftJsonJsonSerializer); INamedTypeSymbol?jsonNetJsonConvertTypeSymbol = wellKnownTypeProvider.GetOrCreateTypeByMetadataName( WellKnownTypeNames.NewtonsoftJsonJsonConvert); if (dataContractSerializerTypeSymbol == null && dataContractJsonSerializerTypeSymbol == null && javaScriptSerializerTypeSymbol == null && xmlSerializerTypeSymbol == null && jsonNetJsonSerializerTypeSymbol == null && jsonNetJsonConvertTypeSymbol == null) { return; } InsecureDeserializationTypeDecider decider = InsecureDeserializationTypeDecider.GetOrCreate(compilation); compilationStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; if (!IsDeserializationMethod( invocationOperation, out ObjectGraphOptions? optionsToUse, out IEnumerable <(ITypeSymbol DeserializedTypeSymbol, IOperation OperationForLocation)>?deserializedTypes)) { return; } RoslynDebug.Assert(optionsToUse != null); RoslynDebug.Assert(deserializedTypes != null); ReportDiagnosticsForInsecureTypes(operationAnalysisContext, optionsToUse, deserializedTypes); }, OperationKind.Invocation); compilationStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IObjectCreationOperation objectCreationOperation = (IObjectCreationOperation)operationAnalysisContext.Operation; if (!IsDeserializationConstructor( objectCreationOperation, out ObjectGraphOptions? optionsToUse, out IEnumerable <(ITypeSymbol DeserializedTypeSymbol, IOperation OperationForLocation)>?deserializedTypes)) { return; } RoslynDebug.Assert(optionsToUse != null); RoslynDebug.Assert(deserializedTypes != null); ReportDiagnosticsForInsecureTypes(operationAnalysisContext, optionsToUse, deserializedTypes); }, OperationKind.ObjectCreation); return; // Local functions. // Determines if the invoked method is for deserialization, and what type of deserialization. bool IsDeserializationMethod( IInvocationOperation invocationOperation, out ObjectGraphOptions? optionsToUse, out IEnumerable <(ITypeSymbol DeserializedTypeSymbol, IOperation OperationForLocation)>?deserializedTypes) { optionsToUse = null; deserializedTypes = null; IMethodSymbol targetMethod = invocationOperation.TargetMethod; if (invocationOperation.Instance?.Type?.DerivesFrom(javaScriptSerializerTypeSymbol) == true) { if (targetMethod.MetadataName == "DeserializeObject" && invocationOperation.Parent?.Kind == OperationKind.Conversion && invocationOperation.Parent is IConversionOperation javaScriptConversionOperation) { optionsToUse = ObjectGraphOptions.JavaScriptSerializerOptions; deserializedTypes = new[] { (javaScriptConversionOperation.Type, (IOperation)javaScriptConversionOperation) }; }
private void AnalyzeObjectCreationForXmlTextReader(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation) { if (variable == null || !_xmlTextReaderEnvironments.TryGetValue(variable, out XmlTextReaderEnvironment env)) { env = new XmlTextReaderEnvironment(_isFrameworkSecure) { XmlTextReaderDefinition = objCreation.Syntax }; } if (objCreation.Constructor.ContainingType != _xmlTypes.XmlTextReader) { env.IsDtdProcessingDisabled = true; env.IsSecureResolver = true; } if (objCreation.Initializer != null) { foreach (IOperation init in objCreation.Initializer.Initializers) { if (init is IAssignmentOperation assign) { var propValue = assign.Value; IPropertySymbol prop = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree)?.GetSymbolInfo(assign.Target.Syntax).Symbol as IPropertySymbol; if (prop == null) { continue; } if (propValue is IConversionOperation operation && SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(prop, _xmlTypes)) { env.IsXmlResolverSet = true; if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { env.IsSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { env.IsSecureResolver = true; } else { env.IsSecureResolver = false; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(prop, _xmlTypes)) { env.IsDtdProcessingSet = true; env.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(propValue); } } } }
private void OnCompilationStart(CompilationStartAnalysisContext compilationContext) { var restrictedInternalsVisibleToMap = GetRestrictedInternalsVisibleToMap(compilationContext.Compilation); if (restrictedInternalsVisibleToMap.IsEmpty) { return; } var namespaceToIsBannedMap = new ConcurrentDictionary <INamespaceSymbol, /*isBanned*/ bool>(); // Verify all explicit type name specifications in declarations and executable code. compilationContext.RegisterSyntaxNodeAction( context => { var name = (TNameSyntax)context.Node; if (!IsInTypeOnlyContext(name) || name.Parent is TNameSyntax) { // Bail out if we are not in type only context or the parent is also a name // which will be analyzed separately. return; } var typeInfo = context.SemanticModel.GetTypeInfo(name, context.CancellationToken); VerifySymbol(typeInfo.Type as INamedTypeSymbol, name, context.ReportDiagnostic, restrictedInternalsVisibleToMap, namespaceToIsBannedMap); }, NameSyntaxKinds); // Verify all member usages in executable code. compilationContext.RegisterOperationAction( context => { var symbol = context.Operation switch { IObjectCreationOperation objectCreation => objectCreation.Constructor, IInvocationOperation invocation => invocation.TargetMethod, IMemberReferenceOperation memberReference => memberReference.Member, IConversionOperation conversion => conversion.OperatorMethod, IUnaryOperation unary => unary.OperatorMethod, IBinaryOperation binary => binary.OperatorMethod, IIncrementOrDecrementOperation incrementOrDecrement => incrementOrDecrement.OperatorMethod, _ => throw new NotImplementedException($"Unhandled OperationKind: {context.Operation.Kind}"), }; VerifySymbol(symbol, context.Operation.Syntax, context.ReportDiagnostic, restrictedInternalsVisibleToMap, namespaceToIsBannedMap); }, OperationKind.ObjectCreation, OperationKind.Invocation, OperationKind.EventReference, OperationKind.FieldReference, OperationKind.MethodReference, OperationKind.PropertyReference, OperationKind.Conversion, OperationKind.UnaryOperator, OperationKind.BinaryOperator, OperationKind.Increment, OperationKind.Decrement); }
protected override void PostProcessArgument(IArgumentOperation operation, bool isEscaped) { base.PostProcessArgument(operation, isEscaped); if (isEscaped) { // Discover if a disposable object is being passed into the creation method for this new disposable object // and if the new disposable object assumes ownership of that passed in disposable object. if (IsDisposeOwnershipTransfer()) { var pointsToValue = GetPointsToAbstractValue(operation.Value); HandlePossibleEscapingOperation(operation, pointsToValue.Locations); return; } else if (FlowBranchConditionKind == ControlFlowConditionKind.WhenFalse && operation.Parameter.RefKind == RefKind.Out && operation.Parent is IInvocationOperation invocation && invocation.TargetMethod.ReturnType.SpecialType == SpecialType.System_Boolean) { // Case 1: // // Assume 'obj' is not a valid object on the 'else' path. // if (TryXXX(out IDisposable obj)) // { // obj.Dispose(); // } // // return; // Case 2: // if (!TryXXX(out IDisposable obj)) // { // return; // Assume 'obj' is not a valid object on this path. // } // // obj.Dispose(); HandlePossibleInvalidatingOperation(operation); return; } } // Ref or out argument values from callee might be escaped by assigning to field. if (operation.Parameter.RefKind == RefKind.Out || operation.Parameter.RefKind == RefKind.Ref) { HandlePossibleEscapingOperation(operation, GetEscapedLocations(operation)); } return; // Local functions. bool IsDisposeOwnershipTransfer() { if (operation.Parameter.RefKind == RefKind.Out) { // Out arguments are always owned by the caller. return(false); } return(operation.Parent switch { IObjectCreationOperation _ => DisposeOwnershipTransferAtConstructor || DisposeOwnershipTransferLikelyTypes.Contains(operation.Parameter.Type), IInvocationOperation invocation => DisposeOwnershipTransferAtMethodCall || IsDisposableCreationSpecialCase(invocation.TargetMethod) && DisposeOwnershipTransferLikelyTypes.Contains(operation.Parameter.Type), _ => false, }); }
public override NullAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) { var _ = base.VisitObjectCreation(operation, argument); return(NullAbstractValue.NotNull); }
private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation) { if (variable == null || !_xmlDocumentEnvironments.TryGetValue(variable, out var xmlDocumentEnvironment)) { xmlDocumentEnvironment = new XmlDocumentEnvironment { IsSecureResolver = false, IsXmlResolverSet = false }; } xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax; SyntaxNode node = objCreation.Syntax; bool isXmlDocumentSecureResolver = false; if (!Equals(objCreation.Constructor.ContainingType, _xmlTypes.XmlDocument)) { isXmlDocumentSecureResolver = true; } // propertyInitlizer is not returned any more // and no way to get propertysymbol if (objCreation.Initializer != null) { foreach (IOperation init in objCreation.Initializer.Initializers) { if (init is IAssignmentOperation assign) { var propValue = assign.Value; if (!(assign.Target is IPropertyReferenceOperation propertyReference)) { continue; } var prop = propertyReference.Property; if (prop.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver")) { if (!(propValue is IConversionOperation operation)) { return; } if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { isXmlDocumentSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { isXmlDocumentSecureResolver = true; } else // Non secure resolvers { context.ReportDiagnostic(assign.Syntax.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver)); return; } } else { AnalyzeNeverSetProperties(context, prop, assign.Syntax.GetLocation()); } } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object { context.ReportDiagnostic(node.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver)); } return; }
public override PropertySetAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object?argument) { PropertySetAbstractValue abstractValue = base.VisitObjectCreation(operation, argument); if (this.TrackedTypeSymbols.Any(s => operation.Type.GetBaseTypesAndThis().Contains(s))) { ConstructorMapper constructorMapper = this.DataFlowAnalysisContext.ConstructorMapper; if (!constructorMapper.PropertyAbstractValues.IsEmpty) { abstractValue = PropertySetAbstractValue.GetInstance(constructorMapper.PropertyAbstractValues); } else if (constructorMapper.MapFromPointsToAbstractValue != null) { using ArrayBuilder <PointsToAbstractValue> builder = ArrayBuilder <PointsToAbstractValue> .GetInstance(); foreach (IArgumentOperation argumentOperation in operation.Arguments) { builder.Add(this.GetPointsToAbstractValue(argumentOperation)); } abstractValue = constructorMapper.MapFromPointsToAbstractValue(operation.Constructor, builder); } else if (constructorMapper.MapFromValueContentAbstractValue != null) { Debug.Assert(this.DataFlowAnalysisContext.ValueContentAnalysisResult != null); using ArrayBuilder <PointsToAbstractValue> pointsToBuilder = ArrayBuilder <PointsToAbstractValue> .GetInstance(); using ArrayBuilder <ValueContentAbstractValue> valueContentBuilder = ArrayBuilder <ValueContentAbstractValue> .GetInstance(); foreach (IArgumentOperation argumentOperation in operation.Arguments) { pointsToBuilder.Add(this.GetPointsToAbstractValue(argumentOperation)); valueContentBuilder.Add(this.GetValueContentAbstractValue(argumentOperation.Value)); } abstractValue = constructorMapper.MapFromValueContentAbstractValue(operation.Constructor, valueContentBuilder, pointsToBuilder); } else { Debug.Fail("Unhandled ConstructorMapper"); return(abstractValue); } PointsToAbstractValue pointsToAbstractValue = this.GetPointsToAbstractValue(operation); this.SetAbstractValue(pointsToAbstractValue, abstractValue); } else { if (TryFindNonTrackedTypeHazardousUsageEvaluator( operation.Constructor, operation.Arguments, out HazardousUsageEvaluator? hazardousUsageEvaluator, out IOperation? propertySetInstance)) { this.EvaluatePotentialHazardousUsage( operation.Syntax, operation.Constructor, propertySetInstance, (PropertySetAbstractValue abstractValue) => hazardousUsageEvaluator.InvocationEvaluator !( operation.Constructor, abstractValue)); } } return(abstractValue); }
public sealed override void Initialize(AnalysisContext context) { ImmutableHashSet <string> cachedDeserializationMethodNames = this.DeserializationMethodNames; Debug.Assert(!string.IsNullOrWhiteSpace(this.DeserializerTypeMetadataName)); Debug.Assert(!string.IsNullOrWhiteSpace(this.SerializationBinderPropertyMetadataName)); Debug.Assert(!cachedDeserializationMethodNames.IsEmpty); Debug.Assert(this.BinderDefinitelyNotSetDescriptor != null); Debug.Assert(this.BinderMaybeNotSetDescriptor != null); context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); // For PropertySetAnalysis dataflow analysis. PropertyMapperCollection propertyMappers = new PropertyMapperCollection( new PropertyMapper( this.SerializationBinderPropertyMetadataName, PropertySetCallbacks.FlagIfNull)); HazardousUsageEvaluatorCollection hazardousUsageEvaluators = new HazardousUsageEvaluatorCollection( cachedDeserializationMethodNames.Select( methodName => new HazardousUsageEvaluator( methodName, PropertySetCallbacks.HazardousIfAllFlaggedOrAllUnknown))); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( this.DeserializerTypeMetadataName, out INamedTypeSymbol? deserializerTypeSymbol)) { return; } PooledHashSet <(IOperation Operation, ISymbol ContainingSymbol)> rootOperationsNeedingAnalysis = PooledHashSet <(IOperation, ISymbol)> .GetInstance(); compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { var owningSymbol = operationBlockStartAnalysisContext.OwningSymbol; // TODO: Handle case when exactly one of the below rules is configured to skip analysis. if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, BinderDefinitelyNotSetDescriptor !, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, BinderMaybeNotSetDescriptor !, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) { return; } operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IObjectCreationOperation creationOperation = (IObjectCreationOperation)operationAnalysisContext.Operation; if (deserializerTypeSymbol.Equals(creationOperation.Type)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add((operationAnalysisContext.Operation.GetRoot(), operationAnalysisContext.ContainingSymbol)); } } }, OperationKind.ObjectCreation); operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; if (Equals(invocationOperation.Instance?.Type, deserializerTypeSymbol) && cachedDeserializationMethodNames.Contains(invocationOperation.TargetMethod.Name)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add((operationAnalysisContext.Operation.GetRoot(), operationAnalysisContext.ContainingSymbol)); } } }, OperationKind.Invocation); operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IMethodReferenceOperation methodReferenceOperation = (IMethodReferenceOperation)operationAnalysisContext.Operation; if (Equals(methodReferenceOperation.Instance?.Type, deserializerTypeSymbol) && cachedDeserializationMethodNames.Contains( methodReferenceOperation.Method.MetadataName)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add((operationAnalysisContext.Operation.GetRoot(), operationAnalysisContext.ContainingSymbol)); } } }, OperationKind.MethodReference); }); compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { PooledDictionary <(Location Location, IMethodSymbol?Method), HazardousUsageEvaluationResult>?allResults = null; try { lock (rootOperationsNeedingAnalysis) { if (!rootOperationsNeedingAnalysis.Any()) { return; } allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, compilationAnalysisContext.Options, this.DeserializerTypeMetadataName, DoNotUseInsecureDeserializerWithoutBinderBase.ConstructorMapper, propertyMappers, hazardousUsageEvaluators, InterproceduralAnalysisConfiguration.Create( compilationAnalysisContext.Options, SupportedDiagnostics, rootOperationsNeedingAnalysis.First().Operation.Syntax.SyntaxTree, compilationAnalysisContext.Compilation, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: compilationAnalysisContext.CancellationToken)); } if (allResults == null) { return; } foreach (KeyValuePair <(Location Location, IMethodSymbol?Method), HazardousUsageEvaluationResult> kvp in allResults) { DiagnosticDescriptor descriptor; switch (kvp.Value) { case HazardousUsageEvaluationResult.Flagged: descriptor = this.BinderDefinitelyNotSetDescriptor !; break; case HazardousUsageEvaluationResult.MaybeFlagged: descriptor = this.BinderMaybeNotSetDescriptor !; break; default: Debug.Fail($"Unhandled result value {kvp.Value}"); continue; } RoslynDebug.Assert(kvp.Key.Method != null); // HazardousUsageEvaluations only for invocations. compilationAnalysisContext.ReportDiagnostic( Diagnostic.Create( descriptor, kvp.Key.Location, kvp.Key.Method.ToDisplayString( SymbolDisplayFormat.MinimallyQualifiedFormat))); } } finally { rootOperationsNeedingAnalysis.Free(compilationAnalysisContext.CancellationToken); allResults?.Free(compilationAnalysisContext.CancellationToken); } }); }); }
private static async Task <Document> SwapArgumentsOrderAsync(Document document, IObjectCreationOperation creation, int paramPosition, int argumentCount, CancellationToken token) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, token).ConfigureAwait(false); SyntaxNode parameter = AddNameOfIfLiteral(creation.Arguments[paramPosition].Value, editor.Generator); SyntaxNode newCreation; if (argumentCount == 2) { if (paramPosition == 0) { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, creation.Arguments[1].Syntax, parameter); } else { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, parameter, creation.Arguments[0].Syntax); } } else { Debug.Assert(argumentCount == 3); if (paramPosition == 0) { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, creation.Arguments[1].Syntax, parameter, creation.Arguments[2].Syntax); } else { newCreation = editor.Generator.ObjectCreationExpression(creation.Type, parameter, creation.Arguments[1].Syntax, creation.Arguments[0].Syntax); } } editor.ReplaceNode(creation.Syntax, newCreation); return(editor.GetChangedDocument()); }
private bool IsViolatingCodeActionObjectCreation(IObjectCreationOperation objectCreation) { return(objectCreation.Constructor.ContainingType.GetBaseTypesAndThis().All(namedType => !IsCodeActionWithOverriddenEquivalenceKey(namedType))); }
public override PointsToAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) { return(VisitTypeCreationWithArgumentsAndInitializer(operation.Arguments, operation.Initializer, operation, argument)); }
public override IOperation VisitObjectCreation(IObjectCreationOperation operation, object argument) { return(new ObjectCreationExpression(operation.Constructor, Visit(operation.Initializer), VisitArray(operation.Arguments), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)); }
private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation) { XmlDocumentEnvironment xmlDocumentEnvironment; if (variable == null || !_xmlDocumentEnvironments.TryGetValue(variable, out xmlDocumentEnvironment)) { xmlDocumentEnvironment = new XmlDocumentEnvironment { IsSecureResolver = false, IsXmlResolverSet = false }; } xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax; SyntaxNode node = objCreation.Syntax; bool isXmlDocumentSecureResolver = false; if (objCreation.Constructor.ContainingType != _xmlTypes.XmlDocument) { isXmlDocumentSecureResolver = true; } // propertyInitlizer is not returned any more // and no way to get propertysymbol if (objCreation.Initializer != null) { foreach (IOperation init in objCreation.Initializer.Initializers) { if (init is IAssignmentOperation assign) { var propValue = assign.Value; IPropertySymbol prop = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree)?.GetSymbolInfo(assign.Target.Syntax).Symbol as IPropertySymbol; if (prop == null) { continue; } if (prop.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver")) { IConversionOperation operation = propValue as IConversionOperation; if (operation == null) { return; } if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { isXmlDocumentSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { isXmlDocumentSecureResolver = true; } else // Non secure resolvers { return; } } } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(MicrosoftNetFrameworkAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } }