예제 #1
0
        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);
        }
예제 #2
0
        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));
        }
예제 #4
0
            static bool NoInitializer(IArrayCreationOperation o)
            {
                var initializer = o.Initializer;

                return(!(initializer is null) &&
                       !initializer.ElementValues.Any());
            }
예제 #5
0
 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);
     }
 }
예제 #6
0
        private static AbstractExpression ReadArrayCreation(IArrayCreationOperation op)
        {
            var context = CodeReaderContext.GetContextOrThrow();

            //TODO: implement properly
            return(new NewArrayExpression());
        }
예제 #7
0
            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);
            }
예제 #8
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);
        }
예제 #10
0
        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));
        }
예제 #11
0
        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
            });
예제 #12
0
            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);
            }
예제 #13
0
        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);
        }
예제 #14
0
        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()));
                }
            }
        }
예제 #15
0
        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);
                }
            }
예제 #17
0
        /// <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));
        }
예제 #18
0
        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));
        }
예제 #19
0
 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();
 }
예제 #21
0
 public override void VisitArrayCreation(IArrayCreationOperation operation)
 {
     Callback(operation.Type, operation.Initializer?.Type);
     base.VisitArrayCreation(operation);
 }
예제 #22
0
 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.
 }
예제 #24
0
 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.
 }
예제 #26
0
 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)
 {
 }
예제 #29
0
 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));
 }