MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Linq;5using System.Management.Automation.Internal;6using System.Management.Automation.Language;7 8// ReSharper disable UnusedMember.Local9 10namespace System.Management.Automation11{12 using Dbg = Diagnostics;13 using System.Collections.ObjectModel;14 15 internal static class VariableOps16 {17 internal static object SetVariableValue(VariablePath variablePath, object value, ExecutionContext executionContext, AttributeBaseAst[] attributeAsts)18 {19 SessionStateInternal sessionState = executionContext.EngineSessionState;20 CommandOrigin origin = sessionState.CurrentScope.ScopeOrigin;21 22 if (!variablePath.IsVariable)23 {24 sessionState.SetVariable(variablePath, value, true, origin);25 return value;26 }27 28 // Variable assignment is traced only if trace level 2 is specified.29 if (executionContext.PSDebugTraceLevel > 1)30 {31 executionContext.Debugger.TraceVariableSet(variablePath.UnqualifiedPath, value);32 }33 34 if (variablePath.IsUnscopedVariable)35 {36 variablePath = variablePath.CloneAndSetLocal();37 }38 39 SessionStateScope scope;40 PSVariable var = sessionState.GetVariableItem(variablePath, out scope, origin);41 42 if (var == null)43 {44 var attributes = attributeAsts == null45 ? new Collection<Attribute>()46 : GetAttributeCollection(attributeAsts);47 var = new PSVariable(variablePath.UnqualifiedPath, value, ScopedItemOptions.None, attributes);48 49 if (attributes.Count > 0)50 {51 // When there are any attributes, it's possible the value was converted/transformed.52 // Use 'GetValueRaw' here so the debugger check won't be triggered.53 value = var.GetValueRaw();54 }55 56 // Marking untrusted values for assignments in 'ConstrainedLanguage' mode is done in57 // SessionStateScope.SetVariable.58 sessionState.SetVariable(variablePath, var, false, origin);59 60 if (executionContext._debuggingMode > 0)61 {62 executionContext.Debugger.CheckVariableWrite(variablePath.UnqualifiedPath);63 }64 }65 else66 {67 if (attributeAsts != null)68 {69 // Use bytewise operation directly instead of 'var.IsReadOnly || var.IsConstant' on70 // a hot path (setting variable with type constraint) to get better performance.71 if ((var.Options & (ScopedItemOptions.ReadOnly | ScopedItemOptions.Constant)) != ScopedItemOptions.None)72 {73 SessionStateUnauthorizedAccessException e =74 new SessionStateUnauthorizedAccessException(75 var.Name,76 SessionStateCategory.Variable,77 "VariableNotWritable",78 SessionStateStrings.VariableNotWritable);79 throw e;80 }81 82 var attributes = GetAttributeCollection(attributeAsts);83 value = PSVariable.TransformValue(attributes, value);84 if (!PSVariable.IsValidValue(attributes, value))85 {86 ValidationMetadataException e = new ValidationMetadataException(87 "ValidateSetFailure",88 null,89 Metadata.InvalidValueFailure,90 var.Name,91 (value != null) ? value.ToString() : "$null");92 93 throw e;94 }95 96 var.SetValueRaw(value, true);97 // Don't update the PSVariable's attributes until we successfully set the value98 var.Attributes.Clear();99 var.AddParameterAttributesNoChecks(attributes);100 101 if (executionContext._debuggingMode > 0)102 {103 executionContext.Debugger.CheckVariableWrite(variablePath.UnqualifiedPath);104 }105 }106 else107 {108 // The setter will handle checking for variable writes.109 var.Value = value;110 }111 112 if (executionContext.LanguageMode == PSLanguageMode.ConstrainedLanguage)113 {114 // Mark untrusted values for assignments to 'Global:' variables, and 'Script:' variables in115 // a module scope, if it's necessary.116 ExecutionContext.MarkObjectAsUntrustedForVariableAssignment(var, scope, sessionState);117 }118 }119 120 return value;121 }122 123 private static bool ThrowStrictModeUndefinedVariable(ExecutionContext executionContext, VariableExpressionAst varAst)124 {125 // In some limited cases, the compiler knows we don't want an error, like when we're backing up126 // $foreach and $switch, which might not be set. In that case, the ast passed is null.127 if (varAst == null)128 {129 return false;130 }131 132 if (executionContext.IsStrictVersion(2))133 {134 return true;135 }136 137 if (executionContext.IsStrictVersion(1))138 {139 var parent = varAst.Parent;140 while (parent != null)141 {142 if (parent is ExpandableStringExpressionAst)143 {144 return false;145 }146 147 parent = parent.Parent;148 }149 150 return true;151 }152 153 return false;154 }155 156 internal static object GetAutomaticVariableValue(int tupleIndex, ExecutionContext executionContext, VariableExpressionAst varAst)157 {158 Diagnostics.Assert(tupleIndex < SpecialVariables.AutomaticVariableTypes.Length, "caller to verify a valid tuple index is used");159 160 if (executionContext._debuggingMode > 0)161 {162 executionContext.Debugger.CheckVariableRead(SpecialVariables.AutomaticVariables[tupleIndex]);163 }164 165 object result = executionContext.EngineSessionState.GetAutomaticVariableValue((AutomaticVariable)tupleIndex);166 167 if (result == AutomationNull.Value)168 {169 if (ThrowStrictModeUndefinedVariable(executionContext, varAst))170 {171 throw InterpreterError.NewInterpreterException(SpecialVariables.AutomaticVariables[tupleIndex], typeof(RuntimeException),172 varAst.Extent, "VariableIsUndefined", ParserStrings.VariableIsUndefined, SpecialVariables.AutomaticVariables[tupleIndex]);173 }174 175 result = null;176 }177 178 return result;179 }180 181 internal static object GetVariableValue(VariablePath variablePath, ExecutionContext executionContext, VariableExpressionAst varAst)182 {183 if (!variablePath.IsVariable)184 {185 CmdletProviderContext contextOut;186 SessionStateScope scopeOut;187 SessionStateInternal ss = executionContext.EngineSessionState;188 return ss.GetVariableValueFromProvider(variablePath, out contextOut, out scopeOut, ss.CurrentScope.ScopeOrigin);189 }190 191 SessionStateInternal sessionState = executionContext.EngineSessionState;192 CommandOrigin origin = sessionState.CurrentScope.ScopeOrigin;193 194 SessionStateScope scope;195 PSVariable var = sessionState.GetVariableItem(variablePath, out scope, origin);196 197 if (var != null)198 {199 return var.Value;200 }201 202 if (sessionState.ExecutionContext._debuggingMode > 0)203 {204 sessionState.ExecutionContext.Debugger.CheckVariableRead(variablePath.UnqualifiedPath);205 }206 207 if (ThrowStrictModeUndefinedVariable(executionContext, varAst))208 {209 throw InterpreterError.NewInterpreterException(variablePath.UserPath, typeof(RuntimeException),210 varAst.Extent, "VariableIsUndefined", ParserStrings.VariableIsUndefined, variablePath.UserPath);211 }212 213 return null;214 }215 216 internal static PSReference GetVariableAsRef(VariablePath variablePath, ExecutionContext executionContext, Type staticType)217 {218 Diagnostics.Assert(variablePath.IsVariable, "calller to verify varpath is a variable.");219 220 SessionStateInternal sessionState = executionContext.EngineSessionState;221 CommandOrigin origin = sessionState.CurrentScope.ScopeOrigin;222 223 SessionStateScope scope;224 PSVariable var = sessionState.GetVariableItem(variablePath, out scope, origin);225 226 if (var == null)227 {228 throw InterpreterError.NewInterpreterException(variablePath, typeof(RuntimeException), null,229 "NonExistingVariableReference",230 ParserStrings.NonExistingVariableReference);231 }232 233 object value = var.Value;234 if (staticType == null && value != null)235 {236 value = PSObject.Base(value);237 if (value != null)238 {239 staticType = value.GetType();240 }241 }242 243 if (staticType == null)244 {245 var declaredType = var.Attributes.OfType<ArgumentTypeConverterAttribute>().FirstOrDefault();246 staticType = declaredType != null ? declaredType.TargetType : typeof(LanguagePrimitives.Null);247 }248 249 return PSReference.CreateInstance(var, staticType);250 }251 252 private static Collection<Attribute> GetAttributeCollection(AttributeBaseAst[] attributeAsts)253 {254 var result = new Collection<Attribute>();255 foreach (var attributeAst in attributeAsts)256 {257 result.Add(attributeAst.GetAttribute());258 }259 260 return result;261 }262 263 private static UsingResult GetUsingValueFromTuple(MutableTuple tuple, string usingExpressionKey, int index)264 {265 var boundParameters =266 tuple.GetAutomaticVariable(AutomaticVariable.PSBoundParameters) as PSBoundParametersDictionary;267 if (boundParameters != null)268 {269 var implicitUsingParameters = boundParameters.ImplicitUsingParameters;270 if (implicitUsingParameters != null)271 {272 if (implicitUsingParameters.Contains(usingExpressionKey))273 {274 return new UsingResult { Value = implicitUsingParameters[usingExpressionKey] };275 }276 else if (implicitUsingParameters.Contains(index))277 {278 // Handle downlevel (V4) using variables by using index to look up using value.279 return new UsingResult { Value = implicitUsingParameters[index] };280 }281 }282 }283 284 return null;285 }286 287 private sealed class UsingResult288 {289 public object Value { get; set; }290 }291 292 internal static object GetUsingValue(MutableTuple tuple, string usingExpressionKey, int index, ExecutionContext context)293 {294 UsingResult result = GetUsingValueFromTuple(tuple, usingExpressionKey, index);295 if (result != null)296 {297 return result.Value;298 }299 300 var scope = context.EngineSessionState.CurrentScope;301 while (scope != null)302 {303 result = GetUsingValueFromTuple(scope.LocalsTuple, usingExpressionKey, index);304 if (result != null)305 {306 return result.Value;307 }308 309 foreach (var dottedScope in scope.DottedScopes)310 {311 result = GetUsingValueFromTuple(dottedScope, usingExpressionKey, index);312 if (result != null)313 {314 return result.Value;315 }316 }317 318 scope = scope.Parent;319 }320 321 // $PSBoundParameters is null or not the expected type (because someone may have assigned to it), so322 // we can't even guess if they were mis-using $using:foo323 throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException),324 null, "UsingWithoutInvokeCommand", ParserStrings.UsingWithoutInvokeCommand);325 }326 }327}328 