Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
ConstantValues.cs579 linesDownload Raw Back to parser
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Diagnostics;6using System.Linq;7using System.Linq.Expressions;8using System.Management.Automation.Internal;9using System.Reflection;10 11namespace System.Management.Automation.Language12{13    /*14     * The IsGetPowerShellSafeValueVisitor class in SafeValues.cs used this class as the basis for implementation.15     * There is a number of similarities between these two classes, and changes (fixes) in this code16     * may need to be reflected in that class and vice versa17     */18    internal class IsConstantValueVisitor : ICustomAstVisitor219    {20        public static bool IsConstant(Ast ast, out object constantValue, bool forAttribute = false, bool forRequires = false)21        {22            try23            {24                if ((bool)ast.Accept(new IsConstantValueVisitor { CheckingAttributeArgument = forAttribute, CheckingRequiresArgument = forRequires }))25                {26                    Ast parent = ast.Parent;27                    while (parent != null)28                    {29                        if (parent is DataStatementAst)30                        {31                            break;32                        }33 34                        parent = parent.Parent;35                    }36 37                    if (parent == null)38                    {39                        constantValue = ast.Accept(new ConstantValueVisitor { AttributeArgument = forAttribute, RequiresArgument = forRequires });40                        return true;41                    }42                }43            }44            catch (Exception)45            {46                // If we get an exception, ignore it and assume the expression isn't constant.47                // This can happen, e.g. if a cast is invalid:48                //     [int]"zed"49            }50 51            constantValue = null;52            return false;53        }54 55        internal bool CheckingAttributeArgument { get; set; }56 57        internal bool CheckingClassAttributeArguments { get; set; }58 59        internal bool CheckingRequiresArgument { get; set; }60 61        public object VisitErrorStatement(ErrorStatementAst errorStatementAst) { return false; }62 63        public object VisitErrorExpression(ErrorExpressionAst errorExpressionAst) { return false; }64 65        public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return false; }66 67        public object VisitParamBlock(ParamBlockAst paramBlockAst) { return false; }68 69        public object VisitNamedBlock(NamedBlockAst namedBlockAst) { return false; }70 71        public object VisitTypeConstraint(TypeConstraintAst typeConstraintAst) { return false; }72 73        public object VisitAttribute(AttributeAst attributeAst) { return false; }74 75        public object VisitNamedAttributeArgument(NamedAttributeArgumentAst namedAttributeArgumentAst) { return false; }76 77        public object VisitParameter(ParameterAst parameterAst) { return false; }78 79        public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { return false; }80 81        public object VisitIfStatement(IfStatementAst ifStmtAst) { return false; }82 83        public object VisitTrap(TrapStatementAst trapStatementAst) { return false; }84 85        public object VisitSwitchStatement(SwitchStatementAst switchStatementAst) { return false; }86 87        public object VisitDataStatement(DataStatementAst dataStatementAst) { return false; }88 89        public object VisitForEachStatement(ForEachStatementAst forEachStatementAst) { return false; }90 91        public object VisitDoWhileStatement(DoWhileStatementAst doWhileStatementAst) { return false; }92 93        public object VisitForStatement(ForStatementAst forStatementAst) { return false; }94 95        public object VisitWhileStatement(WhileStatementAst whileStatementAst) { return false; }96 97        public object VisitCatchClause(CatchClauseAst catchClauseAst) { return false; }98 99        public object VisitTryStatement(TryStatementAst tryStatementAst) { return false; }100 101        public object VisitBreakStatement(BreakStatementAst breakStatementAst) { return false; }102 103        public object VisitContinueStatement(ContinueStatementAst continueStatementAst) { return false; }104 105        public object VisitReturnStatement(ReturnStatementAst returnStatementAst) { return false; }106 107        public object VisitExitStatement(ExitStatementAst exitStatementAst) { return false; }108 109        public object VisitThrowStatement(ThrowStatementAst throwStatementAst) { return false; }110 111        public object VisitDoUntilStatement(DoUntilStatementAst doUntilStatementAst) { return false; }112 113        public object VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) { return false; }114 115        public object VisitCommand(CommandAst commandAst) { return false; }116 117        public object VisitCommandExpression(CommandExpressionAst commandExpressionAst) { return false; }118 119        public object VisitCommandParameter(CommandParameterAst commandParameterAst) { return false; }120 121        public object VisitFileRedirection(FileRedirectionAst fileRedirectionAst) { return false; }122 123        public object VisitMergingRedirection(MergingRedirectionAst mergingRedirectionAst) { return false; }124 125        public object VisitExpandableStringExpression(ExpandableStringExpressionAst expandableStringExpressionAst) { return false; }126 127        public object VisitIndexExpression(IndexExpressionAst indexExpressionAst) { return false; }128 129        public object VisitAttributedExpression(AttributedExpressionAst attributedExpressionAst) { return false; }130 131        public object VisitBlockStatement(BlockStatementAst blockStatementAst) { return false; }132 133        public object VisitInvokeMemberExpression(InvokeMemberExpressionAst invokeMemberExpressionAst) { return false; }134 135        public object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return false; }136 137        public object VisitPropertyMember(PropertyMemberAst propertyMemberAst) { return false; }138 139        public object VisitFunctionMember(FunctionMemberAst functionMemberAst) { return false; }140 141        public object VisitBaseCtorInvokeMemberExpression(BaseCtorInvokeMemberExpressionAst baseCtorInvokeMemberExpressionAst) { return false; }142 143        public object VisitUsingStatement(UsingStatementAst usingStatement) { return false; }144 145        public object VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst) { return false; }146 147        public object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { return false; }148 149        public object VisitStatementBlock(StatementBlockAst statementBlockAst)150        {151            if (statementBlockAst.Traps != null) 152            {153                return false;154            }155 156            if (statementBlockAst.Statements.Count > 1)157            {158                return false;159            }160 161            var pipeline = statementBlockAst.Statements.FirstOrDefault();162            return pipeline != null && (bool)pipeline.Accept(this);163        }164 165        public object VisitPipeline(PipelineAst pipelineAst)166        {167            var expr = pipelineAst.GetPureExpression();168            return expr != null && (bool)expr.Accept(this);169        }170 171        private static bool IsNullDivisor(ExpressionAst operand)172        {173            if (!(operand is VariableExpressionAst varExpr))174            {175                return false;176            }177 178            var parent = operand.Parent as BinaryExpressionAst;179            if (parent == null || parent.Right != operand)180            {181                return false;182            }183 184            switch (parent.Operator)185            {186                case TokenKind.Divide:187                case TokenKind.DivideEquals:188                case TokenKind.Rem:189                case TokenKind.RemainderEquals:190                    string name = varExpr.VariablePath.UnqualifiedPath;191                    return (name.Equals(SpecialVariables.False, StringComparison.OrdinalIgnoreCase) ||192                            name.Equals(SpecialVariables.Null, StringComparison.OrdinalIgnoreCase));193            }194 195            return false;196        }197 198        public object VisitTernaryExpression(TernaryExpressionAst ternaryExpressionAst)199        {200            return (bool)ternaryExpressionAst.Condition.Accept(this) &&201                   (bool)ternaryExpressionAst.IfTrue.Accept(this) &&202                   (bool)ternaryExpressionAst.IfFalse.Accept(this);203        }204 205        public object VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst)206        {207            return binaryExpressionAst.Operator.HasTrait(TokenFlags.CanConstantFold) &&208                (bool)binaryExpressionAst.Left.Accept(this) && (bool)binaryExpressionAst.Right.Accept(this)209                && !IsNullDivisor(binaryExpressionAst.Right);210        }211 212        public object VisitUnaryExpression(UnaryExpressionAst unaryExpressionAst)213        {214            return unaryExpressionAst.TokenKind.HasTrait(TokenFlags.CanConstantFold) &&215                (bool)unaryExpressionAst.Child.Accept(this);216        }217 218        public object VisitConvertExpression(ConvertExpressionAst convertExpressionAst)219        {220            var type = convertExpressionAst.Type.TypeName.GetReflectionType();221            if (type == null)222            {223                return false;224            }225 226            if (!type.IsSafePrimitive())227            {228                // Only do conversions to built-in types - other conversions might not229                // be safe to optimize.230                return false;231            }232 233            return (bool)convertExpressionAst.Child.Accept(this);234        }235 236        public object VisitConstantExpression(ConstantExpressionAst constantExpressionAst)237        {238            return true;239        }240 241        public object VisitStringConstantExpression(StringConstantExpressionAst stringConstantExpressionAst)242        {243            return true;244        }245 246        public object VisitSubExpression(SubExpressionAst subExpressionAst)247        {248            return subExpressionAst.SubExpression.Accept(this);249        }250 251        public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)252        {253            // $using:true should be constant - it's silly to write that, but not harmful.254            return usingExpressionAst.SubExpression.Accept(this);255        }256 257        public object VisitVariableExpression(VariableExpressionAst variableExpressionAst)258        {259            return variableExpressionAst.IsConstantVariable();260        }261 262        public object VisitTypeExpression(TypeExpressionAst typeExpressionAst)263        {264            // We defer trying to resolve a type expression as an attribute argument265            // until the script/function is first run, so it's OK if a type expression266            // as an attribute argument cannot be resolved yet.267            return CheckingAttributeArgument ||268                typeExpressionAst.TypeName.GetReflectionType() != null;269        }270 271        public object VisitMemberExpression(MemberExpressionAst memberExpressionAst)272        {273            if (!memberExpressionAst.Static || memberExpressionAst.Expression is not TypeExpressionAst)274            {275                return false;276            }277 278            var type = ((TypeExpressionAst)memberExpressionAst.Expression).TypeName.GetReflectionType();279            if (type == null)280            {281                return false;282            }283 284            if (!(memberExpressionAst.Member is StringConstantExpressionAst member))285            {286                return false;287            }288 289            var memberInfo = type.GetMember(member.Value, MemberTypes.Field,290                BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);291            if (memberInfo.Length != 1)292            {293                return false;294            }295 296            return (((FieldInfo)memberInfo[0]).Attributes & FieldAttributes.Literal) != 0;297        }298 299        public object VisitArrayExpression(ArrayExpressionAst arrayExpressionAst)300        {301            return false;302        }303 304        public object VisitArrayLiteral(ArrayLiteralAst arrayLiteralAst)305        {306            // An array literal is a constant when we're generating metadata, but when307            // we're generating code, we need to create new arrays or we'd have an aliasing problem.308            return (CheckingAttributeArgument || CheckingRequiresArgument) && arrayLiteralAst.Elements.All(e => (bool)e.Accept(this));309        }310 311        public object VisitHashtable(HashtableAst hashtableAst)312        {313            return CheckingRequiresArgument &&314                   hashtableAst.KeyValuePairs.All(pair => (bool)pair.Item1.Accept(this) && (bool)pair.Item2.Accept(this));315        }316 317        public object VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExpressionAst)318        {319            // A script block expression is a constant when we're generating metadata, but when320            // we're generating code, we need to create new script blocks so we can't use a constant.321            // Also - we have no way to describe a script block when generating .Net metadata, so322            // we must disallow script blocks as attribute arguments on/inside a class.323            return CheckingAttributeArgument && !CheckingClassAttributeArguments;324        }325 326        public object VisitParenExpression(ParenExpressionAst parenExpressionAst)327        {328            return parenExpressionAst.Pipeline.Accept(this);329        }330    }331 332    internal class ConstantValueVisitor : ICustomAstVisitor2333    {334        internal bool AttributeArgument { get; set; }335 336        internal bool RequiresArgument { get; set; }337 338        [Conditional("DEBUG")]339        [Conditional("ASSERTIONS_TRACE")]340        private void CheckIsConstant(Ast ast, string msg)341        {342            Diagnostics.Assert(343                (bool)ast.Accept(new IsConstantValueVisitor { CheckingAttributeArgument = this.AttributeArgument, CheckingRequiresArgument = RequiresArgument }), msg);344        }345 346        private static object CompileAndInvoke(Ast ast)347        {348            try349            {350                var compiler = new Compiler { CompilingConstantExpression = true };351                return Expression.Lambda((Expression)ast.Accept(compiler)).Compile().DynamicInvoke();352            }353            catch (TargetInvocationException tie)354            {355                throw tie.InnerException;356            }357        }358 359        public object VisitErrorStatement(ErrorStatementAst errorStatementAst) { return AutomationNull.Value; }360 361        public object VisitErrorExpression(ErrorExpressionAst errorExpressionAst) { return AutomationNull.Value; }362 363        public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return AutomationNull.Value; }364 365        public object VisitParamBlock(ParamBlockAst paramBlockAst) { return AutomationNull.Value; }366 367        public object VisitNamedBlock(NamedBlockAst namedBlockAst) { return AutomationNull.Value; }368 369        public object VisitTypeConstraint(TypeConstraintAst typeConstraintAst) { return AutomationNull.Value; }370 371        public object VisitAttribute(AttributeAst attributeAst) { return AutomationNull.Value; }372 373        public object VisitNamedAttributeArgument(NamedAttributeArgumentAst namedAttributeArgumentAst) { return AutomationNull.Value; }374 375        public object VisitParameter(ParameterAst parameterAst) { return AutomationNull.Value; }376 377        public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { return AutomationNull.Value; }378 379        public object VisitIfStatement(IfStatementAst ifStmtAst) { return AutomationNull.Value; }380 381        public object VisitTrap(TrapStatementAst trapStatementAst) { return AutomationNull.Value; }382 383        public object VisitSwitchStatement(SwitchStatementAst switchStatementAst) { return AutomationNull.Value; }384 385        public object VisitDataStatement(DataStatementAst dataStatementAst) { return AutomationNull.Value; }386 387        public object VisitForEachStatement(ForEachStatementAst forEachStatementAst) { return AutomationNull.Value; }388 389        public object VisitDoWhileStatement(DoWhileStatementAst doWhileStatementAst) { return AutomationNull.Value; }390 391        public object VisitForStatement(ForStatementAst forStatementAst) { return AutomationNull.Value; }392 393        public object VisitWhileStatement(WhileStatementAst whileStatementAst) { return AutomationNull.Value; }394 395        public object VisitCatchClause(CatchClauseAst catchClauseAst) { return AutomationNull.Value; }396 397        public object VisitTryStatement(TryStatementAst tryStatementAst) { return AutomationNull.Value; }398 399        public object VisitBreakStatement(BreakStatementAst breakStatementAst) { return AutomationNull.Value; }400 401        public object VisitContinueStatement(ContinueStatementAst continueStatementAst) { return AutomationNull.Value; }402 403        public object VisitReturnStatement(ReturnStatementAst returnStatementAst) { return AutomationNull.Value; }404 405        public object VisitExitStatement(ExitStatementAst exitStatementAst) { return AutomationNull.Value; }406 407        public object VisitThrowStatement(ThrowStatementAst throwStatementAst) { return AutomationNull.Value; }408 409        public object VisitDoUntilStatement(DoUntilStatementAst doUntilStatementAst) { return AutomationNull.Value; }410 411        public object VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) { return AutomationNull.Value; }412 413        public object VisitCommand(CommandAst commandAst) { return AutomationNull.Value; }414 415        public object VisitCommandExpression(CommandExpressionAst commandExpressionAst) { return AutomationNull.Value; }416 417        public object VisitCommandParameter(CommandParameterAst commandParameterAst) { return AutomationNull.Value; }418 419        public object VisitFileRedirection(FileRedirectionAst fileRedirectionAst) { return AutomationNull.Value; }420 421        public object VisitMergingRedirection(MergingRedirectionAst mergingRedirectionAst) { return AutomationNull.Value; }422 423        public object VisitExpandableStringExpression(ExpandableStringExpressionAst expandableStringExpressionAst) { return AutomationNull.Value; }424 425        public object VisitIndexExpression(IndexExpressionAst indexExpressionAst) { return AutomationNull.Value; }426 427        public object VisitAttributedExpression(AttributedExpressionAst attributedExpressionAst) { return AutomationNull.Value; }428 429        public object VisitBlockStatement(BlockStatementAst blockStatementAst) { return AutomationNull.Value; }430 431        public object VisitInvokeMemberExpression(InvokeMemberExpressionAst invokeMemberExpressionAst) { return AutomationNull.Value; }432 433        public object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return AutomationNull.Value; }434 435        public object VisitPropertyMember(PropertyMemberAst propertyMemberAst) { return AutomationNull.Value; }436 437        public object VisitFunctionMember(FunctionMemberAst functionMemberAst) { return AutomationNull.Value; }438 439        public object VisitBaseCtorInvokeMemberExpression(BaseCtorInvokeMemberExpressionAst baseCtorInvokeMemberExpressionAst) { return AutomationNull.Value; }440 441        public object VisitUsingStatement(UsingStatementAst usingStatement) { return AutomationNull.Value; }442 443        public object VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst) { return AutomationNull.Value; }444 445        public object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { return AutomationNull.Value; }446 447        public object VisitStatementBlock(StatementBlockAst statementBlockAst)448        {449            CheckIsConstant(statementBlockAst, "Caller to verify ast is constant");450            return statementBlockAst.Statements[0].Accept(this);451        }452 453        public object VisitPipeline(PipelineAst pipelineAst)454        {455            CheckIsConstant(pipelineAst, "Caller to verify ast is constant");456            return pipelineAst.GetPureExpression().Accept(this);457        }458 459        public object VisitTernaryExpression(TernaryExpressionAst ternaryExpressionAst)460        {461            CheckIsConstant(ternaryExpressionAst, "Caller to verify ast is constant");462 463            object condition = ternaryExpressionAst.Condition.Accept(this);464            return LanguagePrimitives.IsTrue(condition)465                ? ternaryExpressionAst.IfTrue.Accept(this)466                : ternaryExpressionAst.IfFalse.Accept(this);467        }468 469        public object VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst)470        {471            CheckIsConstant(binaryExpressionAst, "Caller to verify ast is constant");472            return CompileAndInvoke(binaryExpressionAst);473        }474 475        public object VisitUnaryExpression(UnaryExpressionAst unaryExpressionAst)476        {477            CheckIsConstant(unaryExpressionAst, "Caller to verify ast is constant");478            return CompileAndInvoke(unaryExpressionAst);479        }480 481        public object VisitConvertExpression(ConvertExpressionAst convertExpressionAst)482        {483            CheckIsConstant(convertExpressionAst, "Caller to verify ast is constant");484            return CompileAndInvoke(convertExpressionAst);485        }486 487        public object VisitConstantExpression(ConstantExpressionAst constantExpressionAst)488        {489            CheckIsConstant(constantExpressionAst, "Caller to verify ast is constant");490            return constantExpressionAst.Value;491        }492 493        public object VisitStringConstantExpression(StringConstantExpressionAst stringConstantExpressionAst)494        {495            CheckIsConstant(stringConstantExpressionAst, "Caller to verify ast is constant");496            return stringConstantExpressionAst.Value;497        }498 499        public object VisitSubExpression(SubExpressionAst subExpressionAst)500        {501            CheckIsConstant(subExpressionAst, "Caller to verify ast is constant");502            return subExpressionAst.SubExpression.Accept(this);503        }504 505        public object VisitUsingExpression(UsingExpressionAst usingExpressionAst)506        {507            CheckIsConstant(usingExpressionAst.SubExpression, "Caller to verify ast is constant");508            return usingExpressionAst.SubExpression.Accept(this);509        }510 511        public object VisitVariableExpression(VariableExpressionAst variableExpressionAst)512        {513            CheckIsConstant(variableExpressionAst, "Caller to verify ast is constant");514            string name = variableExpressionAst.VariablePath.UnqualifiedPath;515            if (name.Equals(SpecialVariables.True, StringComparison.OrdinalIgnoreCase))516                return true;517 518            if (name.Equals(SpecialVariables.False, StringComparison.OrdinalIgnoreCase))519                return false;520 521            Diagnostics.Assert(name.Equals(SpecialVariables.Null, StringComparison.OrdinalIgnoreCase), "Unexpected constant variable");522            return null;523        }524 525        public object VisitTypeExpression(TypeExpressionAst typeExpressionAst)526        {527            CheckIsConstant(typeExpressionAst, "Caller to verify ast is constant");528            return typeExpressionAst.TypeName.GetReflectionType();529        }530 531        public object VisitMemberExpression(MemberExpressionAst memberExpressionAst)532        {533            CheckIsConstant(memberExpressionAst, "Caller to verify ast is constant");534 535            var type = ((TypeExpressionAst)memberExpressionAst.Expression).TypeName.GetReflectionType();536            var member = ((StringConstantExpressionAst)memberExpressionAst.Member).Value;537            var memberInfo = type.GetMember(member, MemberTypes.Field,538                BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);539            return ((FieldInfo)memberInfo[0]).GetValue(null);540        }541 542        public object VisitArrayExpression(ArrayExpressionAst arrayExpressionAst)543        {544            CheckIsConstant(arrayExpressionAst, "Caller to verify ast is constant");545            return arrayExpressionAst.SubExpression.Accept(this);546        }547 548        public object VisitArrayLiteral(ArrayLiteralAst arrayLiteralAst)549        {550            CheckIsConstant(arrayLiteralAst, "Caller to verify ast is constant");551            return arrayLiteralAst.Elements.Select(e => e.Accept(this)).ToArray();552        }553 554        public object VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExpressionAst)555        {556            CheckIsConstant(scriptBlockExpressionAst, "Caller to verify ast is constant");557            return new ScriptBlock(scriptBlockExpressionAst.ScriptBlock, isFilter: false);558        }559 560        public object VisitParenExpression(ParenExpressionAst parenExpressionAst)561        {562            CheckIsConstant(parenExpressionAst, "Caller to verify ast is constant");563            return parenExpressionAst.Pipeline.Accept(this);564        }565 566        public object VisitHashtable(HashtableAst hashtableAst)567        {568            CheckIsConstant(hashtableAst, "Caller to verify ast is constant");569            var result = new Hashtable();570            foreach (var pair in hashtableAst.KeyValuePairs)571            {572                result.Add(pair.Item1.Accept(this), pair.Item2.Accept(this));573            }574 575            return result;576        }577    }578}579