public override MultiValue VisitArrayCreation(IArrayCreationOperation operation, StateValue state) { var value = base.VisitArrayCreation(operation, state); // Don't track multi-dimensional arrays if (operation.DimensionSizes.Length != 1) { return(TopValue); } // Don't track large arrays for performance reasons if (operation.Initializer?.ElementValues.Length >= MaxTrackedArrayValues) { return(TopValue); } var arrayValue = ArrayValue.Create(Visit(operation.DimensionSizes[0], state)); var elements = operation.Initializer?.ElementValues.Select(val => Visit(val, state)).ToArray() ?? System.Array.Empty <MultiValue> (); foreach (var array in arrayValue.Cast <ArrayValue> ()) { for (int i = 0; i < elements.Length; i++) { array.IndexValues.Add(i, elements[i]); } } return(arrayValue); }
internal void RegisterOperationAction(CompilationStartAnalysisContext context) { context.RegisterOperationAction( (operationContext) => { IArrayCreationOperation arrayCreation = (IArrayCreationOperation)operationContext.Operation; // ToDo: Need to suppress analysis of array creation expressions within attribute applications. // Detect array creation expression that have rank 1 and size 0. Such expressions // can be replaced with Array.Empty<T>(), provided that the element type can be a generic type argument. var elementType = (arrayCreation as IArrayTypeSymbol)?.ElementType; if ( arrayCreation.DimensionSizes.Length == 1 //// Pointer types can't be generic type arguments. && elementType?.TypeKind != TypeKind.Pointer ) { Optional <object> arrayLength = arrayCreation.DimensionSizes[0].ConstantValue; if ( arrayLength.HasValue && arrayLength.Value is int && (int)arrayLength.Value == 0 ) { Report(operationContext, arrayCreation.Syntax); } } }, OperationKind.ArrayCreation ); }
public override TAbstractAnalysisValue VisitArrayCreation(IArrayCreationOperation operation, object argument) { var value = base.VisitArrayCreation(operation, argument); PointsToAbstractValue instanceLocation = GetPointsToAbstractValue(operation); return(HandleInstanceCreation(operation, instanceLocation, value)); }
static bool NoInitializer(IArrayCreationOperation o) { var initializer = o.Initializer; return(!(initializer is null) && !initializer.ElementValues.Any()); }
protected override void SetAbstractValueForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray <AbstractIndex> indices, ITypeSymbol elementType, IOperation initializer, TAbstractAnalysisValue value) { if (AnalysisEntityFactory.TryCreateForArrayElementInitializer(arrayCreation, indices, elementType, out var analysisEntity)) { SetAbstractValueForAssignment(analysisEntity, initializer, value); } }
private static AbstractExpression ReadArrayCreation(IArrayCreationOperation op) { var context = CodeReaderContext.GetContextOrThrow(); //TODO: implement properly return(new NewArrayExpression()); }
static bool IsZeroSize(IArrayCreationOperation o) { var size = o.DimensionSizes[0].ConstantValue; return(o.Initializer is null && size.HasValue && size.Value is int intValue && intValue == 0); }
private static bool IsZeroLengthArrayCreation(IArrayCreationOperation operation) { if (operation.DimensionSizes.Length != 1) { return(false); } var dimensionSize = operation.DimensionSizes[0].ConstantValue; return(dimensionSize.HasValue && IsZero(dimensionSize.Value));
private bool ArrayContainsString(int index, IArrayCreationOperation arrayCreation) { if (arrayCreation.Initializer.ElementValues.Length <= index) { return(false); } if (arrayCreation.Initializer.ElementValues[index].Type.SpecialType == SpecialType.System_String) { return(true); } if (arrayCreation.Initializer.ElementValues[index] is IConversionOperation conversionOperation) { ITypeSymbol type; if (conversionOperation.Operand is ILiteralOperation literal) { type = literal.Type; } else if (conversionOperation.Operand is IPropertyReferenceOperation property) { type = property.Type; } else if (conversionOperation.Operand is IFieldReferenceOperation field) { type = field.Type; } else if (conversionOperation.Operand is IMethodReferenceOperation method) { type = method.Type; } else if (conversionOperation.Operand is IParameterReferenceOperation parameter) { type = parameter.Type; } else if (conversionOperation.Operand is ILocalReferenceOperation local) { type = local.Type; } else if (conversionOperation.Operand is IInvocationOperation invocation) { type = invocation.Type; } else { return(false); } return(type != null && type.SpecialType == SpecialType.System_String); } return(false); }
private static bool IsCompilerGeneratedParamsArray(IArrayCreationOperation arrayCreationExpression, OperationAnalysisContext context) { var model = arrayCreationExpression.SemanticModel; // Compiler generated array creation seems to just use the syntax from the parent. var parent = model.GetOperation(arrayCreationExpression.Syntax, context.CancellationToken); if (parent == null) { return(false); } ISymbol?targetSymbol = null; var arguments = ImmutableArray <IArgumentOperation> .Empty; if (parent is IInvocationOperation invocation) { targetSymbol = invocation.TargetMethod; arguments = invocation.Arguments; } else { if (parent is IObjectCreationOperation objectCreation) { targetSymbol = objectCreation.Constructor; arguments = objectCreation.Arguments; } else if (parent is IPropertyReferenceOperation propertyReference) { targetSymbol = propertyReference.Property; arguments = propertyReference.Arguments; } } if (targetSymbol == null) { return(false); } var parameters = targetSymbol.GetParameters(); if (parameters.Length == 0 || !parameters[parameters.Length - 1].IsParams) { return(false); } // At this point the array creation is known to be compiler synthesized as part of a call // to a method with a params parameter, and so it is probably sound to return true at this point. // As a sanity check, verify that the last argument to the call is equivalent to the array creation. // (Comparing for object identity does not work because the semantic model can return a fresh operation tree.) var lastArgument = arguments.LastOrDefault(); return(lastArgument != null && lastArgument.Value.Syntax == arrayCreationExpression.Syntax && AreEquivalentZeroLengthArrayCreations(arrayCreationExpression, lastArgument.Value as IArrayCreationOperation)); }
public override Scope VisitArrayCreation(IArrayCreationOperation operation, Scope currentScope) { var newScope = operation.DimensionSizes.Aggregate( currentScope, (scope, size) => size.Accept(this, scope) ); return(operation.Initializer switch { { } initializer => initializer.Accept(this, newScope), null => newScope });
public override PointsToAbstractValue VisitArrayCreation(IArrayCreationOperation operation, object argument) { var pointsToAbstractValue = new PointsToAbstractValue(AbstractLocation.CreateAllocationLocation(operation, operation.Type)); CacheAbstractValue(operation, pointsToAbstractValue); var unusedDimensionsValue = VisitArray(operation.DimensionSizes, argument); var initializerValue = Visit(operation.Initializer, argument); Debug.Assert(operation.Initializer == null || initializerValue == pointsToAbstractValue); return(pointsToAbstractValue); }
public override void VisitArrayCreation(IArrayCreationOperation operation) { Assert.Equal(OperationKind.ArrayCreation, operation.Kind); IEnumerable <IOperation> children = operation.DimensionSizes; if (operation.Initializer != null) { children = children.Concat(new[] { operation.Initializer }); } AssertEx.Equal(children, operation.Children); }
private void AnalyzeOperation(OperationAnalysisContext context) { IArrayCreationOperation creationExpression = (IArrayCreationOperation)context.Operation; if (creationExpression.DimensionSizes.Length == 1 && creationExpression.DimensionSizes[0].ConstantValue.HasValue) { object arrayDimension = creationExpression.DimensionSizes[0].ConstantValue.Value; if (arrayDimension is int && (int)arrayDimension == 0) { context.ReportDiagnostic(Diagnostic.Create(Rule, context.Operation.Syntax.GetLocation())); } } }
private static void AnalyzeOperation(OperationAnalysisContext context, Func <SyntaxNode, bool> isAttributeSytnax) { IArrayCreationOperation arrayCreationExpression = (IArrayCreationOperation)context.Operation; // We can't replace array allocations in attributes, as they're persisted to metadata // TODO: Once we have operation walkers, we can replace this syntactic check with an operation-based check. if (arrayCreationExpression.Syntax.Ancestors().Any(isAttributeSytnax)) { return; } if (arrayCreationExpression.DimensionSizes.Length == 1) { IOperation dimensionSize = arrayCreationExpression.DimensionSizes[0]; if (dimensionSize.HasConstantValue(0)) { // Workaround for https://github.com/dotnet/roslyn/issues/10214 // Bail out for compiler generated params array creation. if (IsCompilerGeneratedParamsArray(arrayCreationExpression, context)) { return; } // pointers can't be used as generic arguments var elementType = arrayCreationExpression.GetElementType(); if (elementType == null) { return; } if (elementType.TypeKind != TypeKind.Pointer) { var arrayType = context.Compilation.GetOrCreateTypeByMetadataName(ArrayTypeName); if (arrayType == null) { return; } IMethodSymbol emptyMethod = (IMethodSymbol)arrayType.GetMembers(ArrayEmptyMethodName).First(); var constructed = emptyMethod.Construct(elementType); string typeName = constructed.ToDisplayString(ReportFormat); context.ReportDiagnostic(arrayCreationExpression.Syntax.CreateDiagnostic(UseArrayEmptyDescriptor, typeName)); } } } }
// So we can treat the array as tainted when it's passed to other object constructors. // See HttpRequest_Form_Array_List_Diagnostic and HttpRequest_Form_List_Diagnostic tests. public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) { HashSet <SymbolAccess> sourceOrigins = null; TaintedDataAbstractValue baseAbstractValue = base.VisitArrayInitializer(operation, argument); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { sourceOrigins = new HashSet <SymbolAccess>(baseAbstractValue.SourceOrigins); } IEnumerable <TaintedDataAbstractValue> taintedAbstractValues = operation.ElementValues .Select <IOperation, TaintedDataAbstractValue>(e => this.GetCachedAbstractValue(e)) .Where(v => v.Kind == TaintedDataAbstractValueKind.Tainted); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { taintedAbstractValues = taintedAbstractValues.Concat(baseAbstractValue); } TaintedDataAbstractValue result = null; if (taintedAbstractValues.Any()) { result = TaintedDataAbstractValue.MergeTainted(taintedAbstractValues); } IArrayCreationOperation arrayCreationOperation = operation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation); if (arrayCreationOperation?.Type is IArrayTypeSymbol arrayTypeSymbol && this.DataFlowAnalysisContext.SourceInfos.IsSourceConstantArrayOfType(arrayTypeSymbol) && operation.ElementValues.All(s => GetValueContentAbstractValue(s).IsLiteralState)) { TaintedDataAbstractValue taintedDataAbstractValue = TaintedDataAbstractValue.CreateTainted(arrayTypeSymbol, arrayCreationOperation.Syntax, this.OwningSymbol); result = result == null ? taintedDataAbstractValue : TaintedDataAbstractValue.MergeTainted(result, taintedDataAbstractValue); } if (result != null) { return(result); } else { return(baseAbstractValue); } }
/// <summary> /// コンストラクタ /// </summary> /// <param name="operation">IOperationインスタンス</param> /// <param name="container">イベントコンテナ</param> public ArrayCreation(IArrayCreationOperation operation, EventContainer container) : base(container) { // newキーワード追加 Expressions.Add(new Expression("new", NewKeywordTypeName)); // 型 var arrayTypeSymbol = operation.Type as IArrayTypeSymbol; var parts = arrayTypeSymbol?.ElementType.ToDisplayParts(SymbolDisplayFormat.MinimallyQualifiedFormat); foreach (var part in parts) { // スペースの場合は型設定に含めない if (part.Kind == SymbolDisplayPartKind.Space) { continue; } var name = Expression.GetSymbolName(part, true); var type = Expression.GetSymbolTypeName(part.Symbol); if (part.Kind == SymbolDisplayPartKind.ClassName) { // 外部ファイル参照イベント発行 RaiseOtherFileReferenced(operation.Syntax, part.Symbol); } Expressions.Add(new Expression(name, type)); } // 要素取得 Expressions.Add(new Expression("[", string.Empty)); for (var i = 0; i < operation.DimensionSizes.Length; i++) { Expressions.AddRange(OperationFactory.GetExpressionList(operation.DimensionSizes[i], container)); if (i >= 0 && i < operation.DimensionSizes.Length - 1) { Expressions.Add(new Expression(",", string.Empty)); } } Expressions.Add(new Expression("]", string.Empty)); }
private static bool AreEquivalentZeroLengthArrayCreations(IArrayCreationOperation first, IArrayCreationOperation second) { if (first == null || second == null) { return(false); } ImmutableArray <IOperation> sizes = first.DimensionSizes; if (sizes.Length != 1 || !sizes[0].HasConstantValue(0)) { return(false); } sizes = second.DimensionSizes; if (sizes.Length != 1 || !sizes[0].HasConstantValue(0)) { return(false); } return(first.Type.Equals(second.Type)); }
public override bool VisitArrayCreation([NotNull] IArrayCreationOperation operation1, [CanBeNull] IOperation argument) { return(argument is IArrayCreationOperation operation2 && AreBaseOperationsEqual(operation1, operation2)); }
public override void VisitArrayCreation([NotNull] IArrayCreationOperation operation) { Result.SetImmediate(); }
public override void VisitArrayCreation(IArrayCreationOperation operation) { Callback(operation.Type, operation.Initializer?.Type); base.VisitArrayCreation(operation); }
public override void VisitArrayCreation([NotNull] IArrayCreationOperation operation) { base.VisitArrayCreation(operation); }
protected override void SetAbstractValueForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray <AbstractIndex> indices, ITypeSymbol elementType, IOperation initializer, ParameterValidationAbstractValue value) { // We are only tracking default parameter locations. }
public static ITypeSymbol GetElementType(this IArrayCreationOperation arrayCreation) { return((arrayCreation?.Type as IArrayTypeSymbol)?.ElementType); }
protected override void SetAbstractValueForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray <AbstractIndex> indices, ITypeSymbol elementType, IOperation initializer, DisposeAbstractValue value) { // Escaping from array element assignment is handled in PointsTo analysis. // We do not need to do anything here. }
public virtual void VisitArrayCreation(IArrayCreationOperation operation) { DefaultVisit(operation); }
public override NullAbstractValue VisitArrayCreation(IArrayCreationOperation operation, object argument) { var _ = base.VisitArrayCreation(operation, argument); return(NullAbstractValue.NotNull); }
protected override void SetAbstractValueForArrayElementInitializer(IArrayCreationOperation arrayCreation, ImmutableArray <AbstractIndex> indices, ITypeSymbol elementType, IOperation initializer, PropertySetAbstractValue value) { }
public override IOperation VisitArrayCreation(IArrayCreationOperation operation, object argument) { return(new ArrayCreationExpression(VisitArray(operation.DimensionSizes), Visit(operation.Initializer), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)); }