Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
SemanticChecks.cs2456 linesDownload Raw Back to parser
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6using System.Diagnostics.CodeAnalysis;7using System.Linq;8using System.Reflection;9using System.Runtime.CompilerServices;10using System.Text;11using System.Text.RegularExpressions;12 13using Microsoft.PowerShell;14using System.Management.Automation.Security;15using System.Management.Automation.Subsystem;16using System.Management.Automation.Subsystem.DSC;17using Microsoft.PowerShell.DesiredStateConfiguration.Internal;18 19namespace System.Management.Automation.Language20{21    internal sealed partial class SemanticChecks : AstVisitor2, IAstPostVisitHandler22    {23        private readonly Parser _parser;24 25        private static readonly IsConstantValueVisitor s_isConstantAttributeArgVisitor = new IsConstantValueVisitor26        {27            CheckingAttributeArgument = true,28        };29 30        private static readonly IsConstantValueVisitor s_isConstantAttributeArgForClassVisitor = new IsConstantValueVisitor31        {32            CheckingAttributeArgument = true,33            CheckingClassAttributeArguments = true34        };35 36        private readonly Stack<MemberAst> _memberScopeStack;37        private readonly Stack<ScriptBlockAst> _scopeStack;38 39        internal static void CheckAst(Parser parser, ScriptBlockAst ast)40        {41            SemanticChecks semanticChecker = new SemanticChecks(parser);42            semanticChecker._scopeStack.Push(ast);43            ast.InternalVisit(semanticChecker);44            semanticChecker._scopeStack.Pop();45            Diagnostics.Assert(semanticChecker._memberScopeStack.Count == 0, "Unbalanced push/pop of member scope stack");46            Diagnostics.Assert(semanticChecker._scopeStack.Count == 0, "Unbalanced push/pop of scope stack");47        }48 49        private SemanticChecks(Parser parser)50        {51            _parser = parser;52            _memberScopeStack = new Stack<MemberAst>();53            _scopeStack = new Stack<ScriptBlockAst>();54        }55 56        private bool AnalyzingStaticMember()57        {58            MemberAst currentMember;59            if (_memberScopeStack.Count == 0 || (currentMember = _memberScopeStack.Peek()) == null)60            {61                return false;62            }63 64            var fnMemberAst = currentMember as FunctionMemberAst;65            return fnMemberAst != null ? fnMemberAst.IsStatic : ((PropertyMemberAst)currentMember).IsStatic;66        }67 68        private static bool IsValidAttributeArgument(Ast ast, IsConstantValueVisitor visitor)69        {70            return (bool)ast.Accept(visitor);71        }72 73        private static (string id, string msg) GetNonConstantAttributeArgErrorExpr(IsConstantValueVisitor visitor)74        {75            if (visitor.CheckingClassAttributeArguments)76            {77                return (nameof(ParserStrings.ParameterAttributeArgumentNeedsToBeConstant),78                    ParserStrings.ParameterAttributeArgumentNeedsToBeConstant);79            }80 81            return (nameof(ParserStrings.ParameterAttributeArgumentNeedsToBeConstantOrScriptBlock),82                ParserStrings.ParameterAttributeArgumentNeedsToBeConstantOrScriptBlock);83        }84 85        private void CheckForDuplicateParameters(ReadOnlyCollection<ParameterAst> parameters)86        {87            if (parameters.Count > 0)88            {89                HashSet<string> parametersSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);90                foreach (var parameter in parameters)91                {92                    string parameterName = parameter.Name.VariablePath.UserPath;93                    if (!parametersSet.Add(parameterName))94                    {95                        _parser.ReportError(parameter.Name.Extent,96                            nameof(ParserStrings.DuplicateFormalParameter),97                            ParserStrings.DuplicateFormalParameter,98                            parameterName);99                    }100 101                    var voidConstraint =102                        parameter.Attributes.OfType<TypeConstraintAst>().FirstOrDefault(static t => typeof(void) == t.TypeName.GetReflectionType());103 104                    if (voidConstraint != null)105                    {106                        _parser.ReportError(voidConstraint.Extent,107                            nameof(ParserStrings.VoidTypeConstraintNotAllowed),108                            ParserStrings.VoidTypeConstraintNotAllowed);109                    }110                }111            }112        }113 114        public override AstVisitAction VisitParamBlock(ParamBlockAst paramBlockAst)115        {116            CheckForDuplicateParameters(paramBlockAst.Parameters);117 118            return AstVisitAction.Continue;119        }120 121        public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstraintAst)122        {123            CheckArrayTypeNameDepth(typeConstraintAst.TypeName, typeConstraintAst.Extent, _parser);124 125            return AstVisitAction.Continue;126        }127 128        public override AstVisitAction VisitAttribute(AttributeAst attributeAst)129        {130            HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);131 132            bool checkingAttributeOnClass = false;133            AttributeTargets attributeTargets = default(AttributeTargets);134 135            var parent = attributeAst.Parent;136            TypeDefinitionAst typeDefinitionAst = parent as TypeDefinitionAst;137            if (typeDefinitionAst != null)138            {139                checkingAttributeOnClass = true;140                attributeTargets = typeDefinitionAst.IsClass141                    ? AttributeTargets.Class142                    : typeDefinitionAst.IsEnum143                        ? AttributeTargets.Enum144                        : AttributeTargets.Interface;145            }146            else if (parent is PropertyMemberAst)147            {148                checkingAttributeOnClass = true;149                attributeTargets = AttributeTargets.Property | AttributeTargets.Field;150            }151            else152            {153                var functionMemberAst = parent as FunctionMemberAst;154                if (functionMemberAst != null)155                {156                    checkingAttributeOnClass = true;157                    attributeTargets = functionMemberAst.IsConstructor158                        ? AttributeTargets.Constructor159                        : AttributeTargets.Method;160                }161                else if (parent is ParameterAst && _memberScopeStack.Peek() is FunctionMemberAst)162                {163                    checkingAttributeOnClass = true;164 165                    // TODO: we aren't actually generating any attributes in the class metadata166                    attributeTargets = AttributeTargets.Parameter;167                }168            }169 170            var constantValueVisitor = checkingAttributeOnClass171                ? s_isConstantAttributeArgForClassVisitor172                : s_isConstantAttributeArgVisitor;173 174            if (checkingAttributeOnClass)175            {176                var attributeType = attributeAst.TypeName.GetReflectionAttributeType();177                if (attributeType == null)178                {179                    Diagnostics.Assert(_parser.ErrorList.Count > 0, "Symbol resolve should have reported error already");180                }181                else182                {183                    var usage = attributeType.GetCustomAttribute<AttributeUsageAttribute>(true);184                    if (usage != null && (usage.ValidOn & attributeTargets) == 0)185                    {186                        _parser.ReportError(attributeAst.Extent,187                            nameof(ParserStrings.AttributeNotAllowedOnDeclaration),188                            ParserStrings.AttributeNotAllowedOnDeclaration,189                            ToStringCodeMethods.Type(attributeType),190                            usage.ValidOn);191                    }192 193                    foreach (var namedArg in attributeAst.NamedArguments)194                    {195                        var name = namedArg.ArgumentName;196                        var members = attributeType.GetMember(name, MemberTypes.Field | MemberTypes.Property,197                            BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance |198                            BindingFlags.FlattenHierarchy);199                        if (members.Length != 1200                            || (members[0] is not PropertyInfo && members[0] is not FieldInfo))201                        {202                            _parser.ReportError(namedArg.Extent,203                                nameof(ParserStrings.PropertyNotFoundForAttribute),204                                ParserStrings.PropertyNotFoundForAttribute,205                                name,206                                ToStringCodeMethods.Type(attributeType),207                                GetValidNamedAttributeProperties(attributeType));208 209                            continue;210                        }211 212                        var propertyInfo = members[0] as PropertyInfo;213                        if (propertyInfo != null)214                        {215                            if (propertyInfo.GetSetMethod() == null)216                            {217                                _parser.ReportError(namedArg.Extent,218                                    nameof(ExtendedTypeSystem.ReadOnlyProperty),219                                    ExtendedTypeSystem.ReadOnlyProperty,220                                    name);221                            }222 223                            continue;224                        }225 226                        var fieldInfo = (FieldInfo)members[0];227                        if (fieldInfo.IsInitOnly || fieldInfo.IsLiteral)228                        {229                            _parser.ReportError(namedArg.Extent,230                                nameof(ExtendedTypeSystem.ReadOnlyProperty),231                                ExtendedTypeSystem.ReadOnlyProperty,232                                name);233                        }234                    }235                }236            }237 238            foreach (var namedArg in attributeAst.NamedArguments)239            {240                string name = namedArg.ArgumentName;241                if (!names.Add(name))242                {243                    _parser.ReportError(namedArg.Extent,244                        nameof(ParserStrings.DuplicateNamedArgument),245                        ParserStrings.DuplicateNamedArgument,246                        name);247                }248                else249                {250                    if (!namedArg.ExpressionOmitted && !IsValidAttributeArgument(namedArg.Argument, constantValueVisitor))251                    {252                        var error = GetNonConstantAttributeArgErrorExpr(constantValueVisitor);253                        _parser.ReportError(namedArg.Argument.Extent, error.id, error.msg);254                    }255                }256            }257 258            foreach (var posArg in attributeAst.PositionalArguments)259            {260                if (!IsValidAttributeArgument(posArg, constantValueVisitor))261                {262                    var error = GetNonConstantAttributeArgErrorExpr(constantValueVisitor);263                    _parser.ReportError(posArg.Extent, error.id, error.msg);264                }265            }266 267            return AstVisitAction.Continue;268        }269 270        private static string GetValidNamedAttributeProperties(Type attributeType)271        {272            var propertyNames = new List<string>();273            PropertyInfo[] properties = attributeType.GetProperties(BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);274            for (int i = 0; i < properties.Length; i++)275            {276                PropertyInfo propertyInfo = properties[i];277                if (propertyInfo.GetSetMethod() != null)278                {279                    propertyNames.Add(propertyInfo.Name);280                }281            }282 283            FieldInfo[] fields = attributeType.GetFields(BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);284            for (int i = 0; i < fields.Length; i++)285            {286                FieldInfo fieldInfo = fields[i];287                if (!fieldInfo.IsInitOnly && !fieldInfo.IsLiteral)288                {289                    propertyNames.Add(fieldInfo.Name);290                }291            }292 293            return string.Join(", ", propertyNames);294        }295 296        public override AstVisitAction VisitParameter(ParameterAst parameterAst)297        {298            bool isClassMethod = parameterAst.Parent.Parent is FunctionMemberAst;299            bool isParamTypeDefined = false;300            foreach (AttributeBaseAst attribute in parameterAst.Attributes)301            {302                if (attribute is TypeConstraintAst)303                {304                    if (attribute.TypeName.FullName.Equals(LanguagePrimitives.OrderedAttribute, StringComparison.OrdinalIgnoreCase))305                    {306                        _parser.ReportError(attribute.Extent,307                            nameof(ParserStrings.OrderedAttributeOnlyOnHashLiteralNode),308                            ParserStrings.OrderedAttributeOnlyOnHashLiteralNode,309                            attribute.TypeName.FullName);310                    }311                    else312                    {313                        if (isClassMethod)314                        {315                            // attribute represent parameter type.316                            if (isParamTypeDefined)317                            {318                                _parser.ReportError(attribute.Extent,319                                    nameof(ParserStrings.MultipleTypeConstraintsOnMethodParam),320                                    ParserStrings.MultipleTypeConstraintsOnMethodParam);321                            }322 323                            isParamTypeDefined = true;324                        }325                    }326                }327            }328 329            return AstVisitAction.Continue;330        }331 332        public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpressionAst)333        {334            CheckArrayTypeNameDepth(typeExpressionAst.TypeName, typeExpressionAst.Extent, _parser);335 336            // If this is access to the [Type] class, it may be suspicious337            if (typeof(Type) == typeExpressionAst.TypeName.GetReflectionType())338            {339                MarkAstParentsAsSuspicious(typeExpressionAst);340            }341 342            return AstVisitAction.Continue;343        }344 345        internal static void CheckArrayTypeNameDepth(ITypeName typeName, IScriptExtent extent, Parser parser)346        {347            int count = 0;348            ITypeName type = typeName;349            while (type is not TypeName)350            {351                count++;352                if (count > 200)353                {354                    parser.ReportError(extent,355                        nameof(ParserStrings.ScriptTooComplicated),356                        ParserStrings.ScriptTooComplicated);357                    break;358                }359 360                if (type is ArrayTypeName)361                {362                    type = ((ArrayTypeName)type).ElementType;363                }364                else365                {366                    break;367                }368            }369        }370 371        public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)372        {373            AttributeAst dscResourceAttributeAst = null;374            for (int i = 0; i < typeDefinitionAst.Attributes.Count; i++)375            {376                var attr = typeDefinitionAst.Attributes[i];377                if (attr.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute))378                {379                    dscResourceAttributeAst = attr;380                    break;381                }382            }383 384            if (dscResourceAttributeAst != null)385            {386                DscResourceChecker.CheckType(_parser, typeDefinitionAst, dscResourceAttributeAst);387            }388 389            return AstVisitAction.Continue;390        }391 392        public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)393        {394            _memberScopeStack.Push(functionMemberAst);395 396            var body = functionMemberAst.Body;397            if (body.ParamBlock != null)398            {399                _parser.ReportError(body.ParamBlock.Extent,400                    nameof(ParserStrings.ParamBlockNotAllowedInMethod),401                    ParserStrings.ParamBlockNotAllowedInMethod);402            }403 404            if (body.BeginBlock != null405                || body.ProcessBlock != null406                || body.CleanBlock != null407                || body.DynamicParamBlock != null408                || !body.EndBlock.Unnamed)409            {410                _parser.ReportError(Parser.ExtentFromFirstOf(body.DynamicParamBlock, body.BeginBlock, body.ProcessBlock, body.EndBlock),411                    nameof(ParserStrings.NamedBlockNotAllowedInMethod),412                    ParserStrings.NamedBlockNotAllowedInMethod);413            }414 415            if (functionMemberAst.IsConstructor && functionMemberAst.ReturnType != null)416            {417                _parser.ReportError(functionMemberAst.ReturnType.Extent,418                    nameof(ParserStrings.ConstructorCantHaveReturnType),419                    ParserStrings.ConstructorCantHaveReturnType);420            }421 422            // Analysis determines if all paths return and do data flow for variables.423            var allCodePathsReturned = VariableAnalysis.AnalyzeMemberFunction(functionMemberAst);424            if (!allCodePathsReturned && !functionMemberAst.IsReturnTypeVoid())425            {426                _parser.ReportError(functionMemberAst.NameExtent ?? functionMemberAst.Extent,427                    nameof(ParserStrings.MethodHasCodePathNotReturn),428                    ParserStrings.MethodHasCodePathNotReturn);429            }430 431            return AstVisitAction.Continue;432        }433 434        public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)435        {436            if (functionDefinitionAst.Parameters != null437                && functionDefinitionAst.Body.ParamBlock != null)438            {439                _parser.ReportError(functionDefinitionAst.Body.ParamBlock.Extent,440                    nameof(ParserStrings.OnlyOneParameterListAllowed),441                    ParserStrings.OnlyOneParameterListAllowed);442            }443            else if (functionDefinitionAst.Parameters != null)444            {445                CheckForDuplicateParameters(functionDefinitionAst.Parameters);446            }447 448            if (functionDefinitionAst.IsWorkflow)449            {450                _parser.ReportError(functionDefinitionAst.Extent,451                    nameof(ParserStrings.WorkflowNotSupportedInPowerShellCore),452                    ParserStrings.WorkflowNotSupportedInPowerShellCore);453            }454 455            return AstVisitAction.Continue;456        }457 458        public override AstVisitAction VisitSwitchStatement(SwitchStatementAst switchStatementAst)459        {460            // Parallel flag not allowed461            if ((switchStatementAst.Flags & SwitchFlags.Parallel) == SwitchFlags.Parallel)462            {463                _parser.ReportError(464                    switchStatementAst.Extent,465                    nameof(ParserStrings.KeywordParameterReservedForFutureUse),466                    ParserStrings.KeywordParameterReservedForFutureUse,467                    "switch",468                    "parallel");469            }470 471            return AstVisitAction.Continue;472        }473 474        private static IEnumerable<string> GetConstantDataStatementAllowedCommands(DataStatementAst dataStatementAst)475        {476            yield return "ConvertFrom-StringData";477            foreach (var allowed in dataStatementAst.CommandsAllowed)478            {479                yield return ((StringConstantExpressionAst)allowed).Value;480            }481        }482 483        public override AstVisitAction VisitDataStatement(DataStatementAst dataStatementAst)484        {485            IEnumerable<string> allowedCommands =486                dataStatementAst.HasNonConstantAllowedCommand ? null : GetConstantDataStatementAllowedCommands(dataStatementAst);487            RestrictedLanguageChecker checker = new RestrictedLanguageChecker(_parser, allowedCommands, null, false);488            dataStatementAst.Body.InternalVisit(checker);489 490            return AstVisitAction.Continue;491        }492 493        public override AstVisitAction VisitForEachStatement(ForEachStatementAst forEachStatementAst)494        {495            // Parallel flag not allowed496            if ((forEachStatementAst.Flags & ForEachFlags.Parallel) == ForEachFlags.Parallel)497            {498                _parser.ReportError(499                    forEachStatementAst.Extent,500                    nameof(ParserStrings.KeywordParameterReservedForFutureUse),501                    ParserStrings.KeywordParameterReservedForFutureUse,502                    "foreach",503                    "parallel");504            }505 506            if (forEachStatementAst.ThrottleLimit != null)507            {508                _parser.ReportError(509                    forEachStatementAst.Extent,510                    nameof(ParserStrings.KeywordParameterReservedForFutureUse),511                    ParserStrings.KeywordParameterReservedForFutureUse,512                    "foreach",513                    "throttlelimit");514            }515 516            // Throttle limit must be combined with Parallel flag517            if ((forEachStatementAst.ThrottleLimit != null) &&518                ((forEachStatementAst.Flags & ForEachFlags.Parallel) != ForEachFlags.Parallel))519            {520                _parser.ReportError(521                    forEachStatementAst.Extent,522                    nameof(ParserStrings.ThrottleLimitRequiresParallelFlag),523                    ParserStrings.ThrottleLimitRequiresParallelFlag);524            }525 526            return AstVisitAction.Continue;527        }528 529        public override AstVisitAction VisitTryStatement(TryStatementAst tryStatementAst)530        {531            if (tryStatementAst.CatchClauses.Count <= 1)532            {533                return AstVisitAction.Continue;534            }535 536            for (int i = 0; i < tryStatementAst.CatchClauses.Count - 1; ++i)537            {538                CatchClauseAst block1 = tryStatementAst.CatchClauses[i];539                for (int j = i + 1; j < tryStatementAst.CatchClauses.Count; ++j)540                {541                    CatchClauseAst block2 = tryStatementAst.CatchClauses[j];542 543                    if (block1.IsCatchAll)544                    {545                        _parser.ReportError(Parser.Before(block2.Extent),546                            nameof(ParserStrings.EmptyCatchNotLast),547                            ParserStrings.EmptyCatchNotLast);548                        break;549                    }550 551                    if (block2.IsCatchAll)552                    {553                        continue;554                    }555 556                    foreach (TypeConstraintAst typeLiteral1 in block1.CatchTypes)557                    {558                        Type type1 = typeLiteral1.TypeName.GetReflectionType();559                        // If the type can't be resolved yet, there isn't much we can do, so skip it.560                        if (type1 == null)561                            continue;562 563                        foreach (TypeConstraintAst typeLiteral2 in block2.CatchTypes)564                        {565                            Type type2 = typeLiteral2.TypeName.GetReflectionType();566                            // If the type can't be resolved yet, there isn't much we can do, so skip it.567                            if (type2 == null)568                                continue;569 570                            if (type1 == type2 || type2.IsSubclassOf(type1))571                            {572                                _parser.ReportError(typeLiteral2.Extent,573                                    nameof(ParserStrings.ExceptionTypeAlreadyCaught),574                                    ParserStrings.ExceptionTypeAlreadyCaught,575                                    type2.FullName);576                            }577                        }578                    }579                }580            }581 582            return AstVisitAction.Continue;583        }584 585        /// <summary>586        /// Check that label exists inside the method.587        /// Only call it, when label is present and can be calculated in compile time.588        /// </summary>589        /// <param name="ast">BreakStatementAst or ContinueStatementAst.</param>590        /// <param name="label">Label name. Can be null.</param>591        private void CheckLabelExists(StatementAst ast, string label)592        {593            if (string.IsNullOrEmpty(label))594            {595                return;596            }597 598            Ast parent;599            for (parent = ast.Parent; parent != null; parent = parent.Parent)600            {601                if (parent is FunctionDefinitionAst)602                {603                    if (parent.Parent is FunctionMemberAst)604                    {605                        _parser.ReportError(ast.Extent,606                            nameof(ParserStrings.LabelNotFound),607                            ParserStrings.LabelNotFound,608                            label);609                    }610 611                    break;612                }613 614                var loop = parent as LoopStatementAst;615                if (loop != null)616                {617                    if (LoopFlowException.MatchLoopLabel(label, loop.Label ?? string.Empty))618                        break;619                }620            }621        }622 623        /// <summary>624        /// Check that flow doesn't leave finally.625        /// </summary>626        /// <param name="ast"></param>627        /// <param name="label">If label is null, either it's a break/continue to an unknown label628        /// (and unknown does not mean not specified, it means it's an expression we can't evaluate) or we have a return statement.629        /// </param>630        private void CheckForFlowOutOfFinally(Ast ast, string label)631        {632            Ast parent;633            for (parent = ast.Parent; parent != null; parent = parent.Parent)634            {635                if (parent is NamedBlockAst || parent is TrapStatementAst || parent is ScriptBlockAst)636                {637                    // Script blocks, traps, and named blocks are all top level asts for a complete method,638                    // so if we didn't find a try/catch, the control flow is just leaving the method,639                    // it is not leaving some finally, even if the script lock/trap is nested in the finally.640                    break;641                }642 643                // If label is not null, we have a break/continue where we know the loop label at compile644                // time. If we can match the label before finding the finally, then we're not flowing out645                // of the finally.646                if (label != null && parent is LabeledStatementAst)647                {648                    if (LoopFlowException.MatchLoopLabel(label, ((LabeledStatementAst)parent).Label ?? string.Empty))649                        break;650                }651 652                var stmtBlock = parent as StatementBlockAst;653                if (stmtBlock != null)654                {655                    var tryStatementAst = stmtBlock.Parent as TryStatementAst;656                    if (tryStatementAst != null && tryStatementAst.Finally == stmtBlock)657                    {658                        _parser.ReportError(ast.Extent,659                            nameof(ParserStrings.ControlLeavingFinally),660                            ParserStrings.ControlLeavingFinally);661                        break;662                    }663                }664            }665        }666 667        private static string GetLabel(ExpressionAst expr)668        {669            // We only return null from this method if the label is unknown.  If no label is specified,670            // we just use the empty string.671            if (expr == null)672            {673                return string.Empty;674            }675 676            var str = expr as StringConstantExpressionAst;677            return str?.Value;678        }679 680        public override AstVisitAction VisitBreakStatement(BreakStatementAst breakStatementAst)681        {682            string label = GetLabel(breakStatementAst.Label);683            CheckForFlowOutOfFinally(breakStatementAst, label);684            CheckLabelExists(breakStatementAst, label);685 686            return AstVisitAction.Continue;687        }688 689        public override AstVisitAction VisitContinueStatement(ContinueStatementAst continueStatementAst)690        {691            string label = GetLabel(continueStatementAst.Label);692            CheckForFlowOutOfFinally(continueStatementAst, label);693            CheckLabelExists(continueStatementAst, label);694 695            return AstVisitAction.Continue;696        }697 698        private void CheckForReturnStatement(ReturnStatementAst ast)699        {700            if (!(_memberScopeStack.Peek() is FunctionMemberAst functionMemberAst))701            {702                return;703            }704 705            if (ast.Pipeline != null)706            {707                if (functionMemberAst.IsReturnTypeVoid())708                {709                    _parser.ReportError(ast.Extent,710                        nameof(ParserStrings.VoidMethodHasReturn),711                        ParserStrings.VoidMethodHasReturn);712                }713            }714            else715            {716                if (!functionMemberAst.IsReturnTypeVoid())717                {718                    _parser.ReportError(ast.Extent,719                        nameof(ParserStrings.NonVoidMethodMissingReturnValue),720                        ParserStrings.NonVoidMethodMissingReturnValue);721                }722            }723        }724 725        public override AstVisitAction VisitReturnStatement(ReturnStatementAst returnStatementAst)726        {727            CheckForFlowOutOfFinally(returnStatementAst, null);728            CheckForReturnStatement(returnStatementAst);729            return AstVisitAction.Continue;730        }731 732        /// <summary>733        /// Check if the ast is a valid target for assignment.  If not, the action reportError is called.734        /// </summary>735        /// <param name="ast">The target of an assignment.</param>736        /// <param name="simpleAssignment">True if the operator '=' is used, false otherwise (e.g. false on '+=' or '++'.).</param>737        /// <param name="reportError">The action called to report any errors.</param>738        private void CheckAssignmentTarget(ExpressionAst ast, bool simpleAssignment, Action<Ast> reportError)739        {740            ArrayLiteralAst arrayLiteralAst = ast as ArrayLiteralAst;741            Ast errorAst = null;742            if (arrayLiteralAst != null)743            {744                if (simpleAssignment)745                {746                    CheckArrayLiteralAssignment(arrayLiteralAst, reportError);747                }748                else749                {750                    errorAst = arrayLiteralAst;751                }752            }753            else754            {755                ParenExpressionAst parenExpressionAst = ast as ParenExpressionAst;756                if (parenExpressionAst != null)757                {758                    ExpressionAst expr = parenExpressionAst.Pipeline.GetPureExpression();759                    if (expr == null)760                    {761                        errorAst = parenExpressionAst.Pipeline;762                    }763                    else764                    {765                        CheckAssignmentTarget(expr, simpleAssignment, reportError);766                    }767                }768                else if (ast is not ISupportsAssignment)769                {770                    errorAst = ast;771                }772                else if (ast is MemberExpressionAst memberExprAst && memberExprAst.NullConditional)773                {774                    errorAst = ast;775                }776                else if (ast is IndexExpressionAst indexExprAst && indexExprAst.NullConditional)777                {778                    errorAst = ast;779                }780                else if (ast is AttributedExpressionAst)781                {782                    // Check for multiple types combined with [ref].783                    ExpressionAst expr = ast;784                    int converts = 0;785                    IScriptExtent errorPosition = null;786                    Type lastConvertType = null;787                    while (expr is AttributedExpressionAst)788                    {789                        var convertExpr = expr as ConvertExpressionAst;790                        if (convertExpr != null)791                        {792                            converts += 1;793                            lastConvertType = convertExpr.Type.TypeName.GetReflectionType();794                            if (typeof(PSReference) == lastConvertType)795                            {796                                errorPosition = convertExpr.Type.Extent;797                            }798                            else if (typeof(void) == lastConvertType)799                            {800                                _parser.ReportError(convertExpr.Type.Extent,801                                    nameof(ParserStrings.VoidTypeConstraintNotAllowed),802                                    ParserStrings.VoidTypeConstraintNotAllowed);803                            }804                        }805 806                        expr = ((AttributedExpressionAst)expr).Child;807                    }808 809                    if ((errorPosition != null) && converts > 1)810                    {811                        _parser.ReportError(errorPosition,812                            nameof(ParserStrings.ReferenceNeedsToBeByItselfInTypeConstraint),813                            ParserStrings.ReferenceNeedsToBeByItselfInTypeConstraint);814                    }815                    else816                    {817                        var varExprAst = expr as VariableExpressionAst;818                        if (varExprAst != null)819                        {820                            var varPath = varExprAst.VariablePath;821                            if (varPath.IsVariable && varPath.IsAnyLocal())822                            {823                                var specialIndex = 0;824                                while (specialIndex < (int)AutomaticVariable.NumberOfAutomaticVariables)825                                {826                                    if (varPath.UnqualifiedPath.Equals(SpecialVariables.AutomaticVariables[specialIndex], StringComparison.OrdinalIgnoreCase))827                                    {828                                        var expectedType = SpecialVariables.AutomaticVariableTypes[specialIndex];829                                        if (expectedType != lastConvertType)830                                        {831                                            _parser.ReportError(ast.Extent,832                                                nameof(ParserStrings.AssignmentStatementToAutomaticNotSupported),833                                                ParserStrings.AssignmentStatementToAutomaticNotSupported,834                                                varPath.UnqualifiedPath,835                                                expectedType);836                                        }837 838                                        break;839                                    }840 841                                    specialIndex += 1;842                                }843                            }844                        }845 846                        CheckAssignmentTarget(expr, simpleAssignment, reportError);847                    }848                }849            }850 851            if (errorAst != null)852            {853                reportError(errorAst);854            }855        }856 857        private void CheckArrayLiteralAssignment(ArrayLiteralAst ast, Action<Ast> reportError)858        {859            RuntimeHelpers.EnsureSufficientExecutionStack();860            foreach (var element in ast.Elements)861            {862                CheckAssignmentTarget(element, true, reportError);863            }864        }865 866        public override AstVisitAction VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst)867        {868            // Make sure LHS is something that can be assigned to.869            CheckAssignmentTarget(assignmentStatementAst.Left, assignmentStatementAst.Operator == TokenKind.Equals,870                ast => _parser.ReportError(ast.Extent,871                    nameof(ParserStrings.InvalidLeftHandSide),872                    ParserStrings.InvalidLeftHandSide));873 874            return AstVisitAction.Continue;875        }876 877        public override AstVisitAction VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst)878        {879            if (binaryExpressionAst.Operator == TokenKind.AndAnd880                || binaryExpressionAst.Operator == TokenKind.OrOr)881            {882                _parser.ReportError(binaryExpressionAst.ErrorPosition,883                    nameof(ParserStrings.InvalidEndOfLine),884                    ParserStrings.InvalidEndOfLine,885                    binaryExpressionAst.Operator.Text());886            }887 888            return AstVisitAction.Continue;889        }890 891        public override AstVisitAction VisitUnaryExpression(UnaryExpressionAst unaryExpressionAst)892        {893            switch (unaryExpressionAst.TokenKind)894            {895                case TokenKind.PlusPlus:896                case TokenKind.PostfixPlusPlus:897                case TokenKind.MinusMinus:898                case TokenKind.PostfixMinusMinus:899                    CheckAssignmentTarget(unaryExpressionAst.Child, false,900                        ast => _parser.ReportError(ast.Extent,901                            nameof(ParserStrings.OperatorRequiresVariableOrProperty),902                            ParserStrings.OperatorRequiresVariableOrProperty,903                            unaryExpressionAst.TokenKind.Text()));904                    break;905            }906 907            return AstVisitAction.Continue;908        }909 910        public override AstVisitAction VisitConvertExpression(ConvertExpressionAst convertExpressionAst)911        {912            if (convertExpressionAst.Type.TypeName.FullName.Equals(LanguagePrimitives.OrderedAttribute, StringComparison.OrdinalIgnoreCase))913            {914                if (convertExpressionAst.Child is not HashtableAst)915                {916                    // We allow the ordered attribute only on hashliteral node.917                    // This check covers the following scenario918                    //   $a = [ordered]10919                    _parser.ReportError(convertExpressionAst.Extent,920                        nameof(ParserStrings.OrderedAttributeOnlyOnHashLiteralNode),921                        ParserStrings.OrderedAttributeOnlyOnHashLiteralNode,922                        convertExpressionAst.Type.TypeName.FullName);923                }924 925                // Currently, the type name '[ordered]' is handled specially in PowerShell.926                // When used in a conversion expression, it's only allowed on a hashliteral node, and it's927                // always interpreted as an initializer for a case-insensitive928                // 'System.Collections.Specialized.OrderedDictionary' by the compiler.929                // So, we can return early from here.930                return AstVisitAction.Continue;931            }932 933            if (typeof(PSReference) == convertExpressionAst.Type.TypeName.GetReflectionType())934            {935                // Check for [ref][ref]936                ExpressionAst child = convertExpressionAst.Child;937                bool multipleRefs = false;938                while (true)939                {940                    var childAttrExpr = child as AttributedExpressionAst;941                    if (childAttrExpr != null)942                    {943                        var childConvert = childAttrExpr as ConvertExpressionAst;944                        if (childConvert != null && typeof(PSReference) == childConvert.Type.TypeName.GetReflectionType())945                        {946                            multipleRefs = true;947                            _parser.ReportError(childConvert.Type.Extent,948                                                nameof(ParserStrings.ReferenceNeedsToBeByItselfInTypeSequence),949                                                ParserStrings.ReferenceNeedsToBeByItselfInTypeSequence);950                        }951 952                        child = childAttrExpr.Child;953                        continue;954                    }955 956                    break;957                }958 959                // Check for [int][ref], but don't add an extra error for [ref][ref].960                var parent = convertExpressionAst.Parent as AttributedExpressionAst;961                while (parent != null)962                {963                    var parentConvert = parent as ConvertExpressionAst;964                    if (parentConvert != null && !multipleRefs)965                    {966                        if (typeof(PSReference) == parentConvert.Type.TypeName.GetReflectionType())967                        {968                            break;969                        }970 971                        // Don't complain if on the lhs of an assign, there is a different error message, and972                        // that is checked as part of assignment.973                        var ast = parent.Parent;974                        bool skipError = false;975                        while (ast != null)976                        {977                            var statementAst = ast as AssignmentStatementAst;978                            if (statementAst != null)979                            {980                                skipError = statementAst.Left.Find(ast1 => ast1 == convertExpressionAst, searchNestedScriptBlocks: true) != null;981                                break;982                            }983 984                            if (ast is CommandExpressionAst)985                            {986                                break;987                            }988 989                            ast = ast.Parent;990                        }991 992                        if (!skipError)993                        {994                            _parser.ReportError(convertExpressionAst.Type.Extent,995                                                nameof(ParserStrings.ReferenceNeedsToBeLastTypeInTypeConversion),996                                                ParserStrings.ReferenceNeedsToBeLastTypeInTypeConversion);997                        }998                    }999 1000                    parent = parent.Child as AttributedExpressionAst;1001                }1002            }1003 1004            // Converting to Type is suspicious1005            if (typeof(Type) == convertExpressionAst.Type.TypeName.GetReflectionType())1006            {1007                MarkAstParentsAsSuspicious(convertExpressionAst);1008            }1009 1010            return AstVisitAction.Continue;1011        }1012 1013        public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst)1014        {1015            // The parser will parse anything that could start with a variable when1016            // creating a UsingExpressionAst, but we will only support "simple"1017            // property and array references with no side effects.1018 1019            var exprAst = usingExpressionAst.SubExpression;1020            var badExpr = CheckUsingExpression(exprAst);1021            if (badExpr != null)1022            {1023                _parser.ReportError(badExpr.Extent,1024                    nameof(ParserStrings.InvalidUsingExpression),1025                    ParserStrings.InvalidUsingExpression);1026            }1027 1028            return AstVisitAction.Continue;1029        }1030 1031        private static ExpressionAst CheckUsingExpression(ExpressionAst exprAst)1032        {1033            RuntimeHelpers.EnsureSufficientExecutionStack();1034            if (exprAst is VariableExpressionAst)1035            {1036                return null;1037            }1038 1039            var memberExpr = exprAst as MemberExpressionAst;1040            if (memberExpr != null1041                && memberExpr is not InvokeMemberExpressionAst1042                && memberExpr.Member is StringConstantExpressionAst)1043            {1044                return CheckUsingExpression(memberExpr.Expression);1045            }1046 1047            var indexExpr = exprAst as IndexExpressionAst;1048            if (indexExpr != null)1049            {1050                if (!IsValidAttributeArgument(indexExpr.Index, s_isConstantAttributeArgVisitor))1051                {1052                    return indexExpr.Index;1053                }1054 1055                return CheckUsingExpression(indexExpr.Target);1056            }1057 1058            return exprAst;1059        }1060 1061        public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)1062        {1063            if (variableExpressionAst.Splatted1064                && variableExpressionAst.Parent is not CommandAst1065                && variableExpressionAst.Parent is not UsingExpressionAst)1066            {1067                if (variableExpressionAst.Parent is ArrayLiteralAst && variableExpressionAst.Parent.Parent is CommandAst)1068                {1069                    _parser.ReportError(variableExpressionAst.Extent,1070                        nameof(ParserStrings.SplattingNotPermittedInArgumentList),1071                        ParserStrings.SplattingNotPermittedInArgumentList,1072                        variableExpressionAst.VariablePath.UserPath);1073                }1074                else1075                {1076                    _parser.ReportError(variableExpressionAst.Extent,1077                        nameof(ParserStrings.SplattingNotPermitted),1078                        ParserStrings.SplattingNotPermitted,1079                        variableExpressionAst.VariablePath.UserPath);1080                }1081            }1082 1083            if (variableExpressionAst.VariablePath.IsVariable)1084            {1085                if (variableExpressionAst.TupleIndex == VariableAnalysis.ForceDynamic1086                    && !variableExpressionAst.Assigned1087                    && !variableExpressionAst.VariablePath.IsGlobal1088                    && !variableExpressionAst.VariablePath.IsScript1089                    && !variableExpressionAst.IsConstantVariable()1090                    && !SpecialVariables.IsImplicitVariableAccessibleInClassMethod(variableExpressionAst.VariablePath))1091                {1092                    _parser.ReportError(variableExpressionAst.Extent,1093                        nameof(ParserStrings.VariableNotLocal),1094                        ParserStrings.VariableNotLocal);1095                }1096            }1097 1098            if (variableExpressionAst.VariablePath.UserPath.Equals(SpecialVariables.This, StringComparison.OrdinalIgnoreCase))1099            {1100                if (AnalyzingStaticMember())1101                {1102                    _parser.ReportError(variableExpressionAst.Extent,1103                        nameof(ParserStrings.NonStaticMemberAccessInStaticMember),1104                        ParserStrings.NonStaticMemberAccessInStaticMember,1105                        variableExpressionAst.VariablePath.UserPath);1106                }1107            }1108 1109            return AstVisitAction.Continue;1110        }1111 1112        public override AstVisitAction VisitHashtable(HashtableAst hashtableAst)1113        {1114            HashSet<string> keys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);1115            foreach (var entry in hashtableAst.KeyValuePairs)1116            {1117                var keyStrAst = entry.Item1 as ConstantExpressionAst;1118                if (keyStrAst != null)1119                {1120                    var keyStr = keyStrAst.Value.ToString();1121                    if (!keys.Add(keyStr))1122                    {1123                        string errorId;1124                        string errorMsg;1125                        if (hashtableAst.IsSchemaElement)1126                        {1127                            errorId = nameof(ParserStrings.DuplicatePropertyInInstanceDefinition);1128                            errorMsg = ParserStrings.DuplicatePropertyInInstanceDefinition;1129                        }1130                        else1131                        {1132                            errorId = nameof(ParserStrings.DuplicateKeyInHashLiteral);1133                            errorMsg = ParserStrings.DuplicateKeyInHashLiteral;1134                        }1135 1136                        _parser.ReportError(entry.Item1.Extent, errorId, errorMsg, keyStr);1137                    }1138                }1139            }1140 1141            return AstVisitAction.Continue;1142        }1143 1144        public override AstVisitAction VisitAttributedExpression(AttributedExpressionAst attributedExpressionAst)1145        {1146            // The attribute (and not the entire expression) is used for the error extent.1147            var errorAst = attributedExpressionAst.Attribute;1148            while (attributedExpressionAst != null)1149            {1150                if (attributedExpressionAst.Child is VariableExpressionAst)1151                {1152                    return AstVisitAction.Continue;1153                }1154 1155                attributedExpressionAst = attributedExpressionAst.Child as AttributedExpressionAst;1156            }1157 1158            _parser.ReportError(errorAst.Extent,1159                nameof(ParserStrings.UnexpectedAttribute),1160                ParserStrings.UnexpectedAttribute,1161                errorAst.TypeName.FullName);1162 1163            return AstVisitAction.Continue;1164        }1165 1166        public override AstVisitAction VisitBlockStatement(BlockStatementAst blockStatementAst)1167        {1168            if (blockStatementAst.IsInWorkflow())1169            {1170                return AstVisitAction.Continue;1171            }1172 1173            _parser.ReportError(blockStatementAst.Kind.Extent,1174                nameof(ParserStrings.UnexpectedKeyword),1175                ParserStrings.UnexpectedKeyword,1176                blockStatementAst.Kind.Text);1177 1178            return AstVisitAction.Continue;1179        }1180 1181        public override AstVisitAction VisitMemberExpression(MemberExpressionAst memberExpressionAst)1182        {1183            CheckMemberAccess(memberExpressionAst);1184            return AstVisitAction.Continue;1185        }1186 1187        public override AstVisitAction VisitInvokeMemberExpression(InvokeMemberExpressionAst memberExpressionAst)1188        {1189            CheckMemberAccess(memberExpressionAst);1190            return AstVisitAction.Continue;1191        }1192 1193        private static void CheckMemberAccess(MemberExpressionAst ast)1194        {1195            // If the member access is not constant, it may be considered suspicious1196            if (ast.Member is not ConstantExpressionAst)1197            {1198                MarkAstParentsAsSuspicious(ast);1199            }1200 

Showing the first 1,200 of 2456 lines. Download the file for the rest.