mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Validate the value for using namespace during semantic checks to prevent declaring invalid namespaces (#21162)
This commit is contained in:
@@ -8,6 +8,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Microsoft.PowerShell;
|
||||
using System.Management.Automation.Security;
|
||||
@@ -17,7 +18,7 @@ using Microsoft.PowerShell.DesiredStateConfiguration.Internal;
|
||||
|
||||
namespace System.Management.Automation.Language
|
||||
{
|
||||
internal sealed class SemanticChecks : AstVisitor2, IAstPostVisitHandler
|
||||
internal sealed partial class SemanticChecks : AstVisitor2, IAstPostVisitHandler
|
||||
{
|
||||
private readonly Parser _parser;
|
||||
|
||||
@@ -1319,20 +1320,50 @@ namespace System.Management.Automation.Language
|
||||
|
||||
public override AstVisitAction VisitUsingStatement(UsingStatementAst usingStatementAst)
|
||||
{
|
||||
bool usingKindSupported = usingStatementAst.UsingStatementKind == UsingStatementKind.Namespace ||
|
||||
usingStatementAst.UsingStatementKind == UsingStatementKind.Assembly ||
|
||||
usingStatementAst.UsingStatementKind == UsingStatementKind.Module;
|
||||
if (!usingKindSupported ||
|
||||
usingStatementAst.Alias != null)
|
||||
UsingStatementKind kind = usingStatementAst.UsingStatementKind;
|
||||
bool usingKindSupported = kind is UsingStatementKind.Namespace or UsingStatementKind.Assembly or UsingStatementKind.Module;
|
||||
if (!usingKindSupported || usingStatementAst.Alias != null)
|
||||
{
|
||||
_parser.ReportError(usingStatementAst.Extent,
|
||||
_parser.ReportError(
|
||||
usingStatementAst.Extent,
|
||||
nameof(ParserStrings.UsingStatementNotSupported),
|
||||
ParserStrings.UsingStatementNotSupported);
|
||||
}
|
||||
|
||||
if (kind is UsingStatementKind.Namespace)
|
||||
{
|
||||
Regex nsPattern = NamespacePattern();
|
||||
if (!nsPattern.IsMatch(usingStatementAst.Name.Value))
|
||||
{
|
||||
_parser.ReportError(
|
||||
usingStatementAst.Name.Extent,
|
||||
nameof(ParserStrings.InvalidNamespaceValue),
|
||||
ParserStrings.InvalidNamespaceValue);
|
||||
}
|
||||
}
|
||||
|
||||
return AstVisitAction.Continue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This regular expression is for validating if a namespace string is valid.
|
||||
///
|
||||
/// In C#, a legit namespace is defined as `identifier ('.' identifier)*` [see https://learn.microsoft.com/dotnet/csharp/language-reference/language-specification/namespaces#143-namespace-declarations].
|
||||
/// And `identifier` is defined in https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/identifier-names#naming-rules, summarized below:
|
||||
/// - Identifiers must start with a letter or underscore (_).
|
||||
/// - Identifiers can contain
|
||||
/// * Unicode letter characters (categories: Lu, Ll, Lt, Lm, Lo or Nl);
|
||||
/// * decimal digit characters (category: Nd);
|
||||
/// * Unicode connecting characters (category: Pc);
|
||||
/// * Unicode combining characters (categories: Mn, Mc);
|
||||
/// * Unicode formatting characters (category: Cf).
|
||||
///
|
||||
/// For details about how Unicode categories are represented in regular expression, see the "Unicode Categories" section in the following article:
|
||||
/// - https://www.regular-expressions.info/unicode.html
|
||||
/// </summary>
|
||||
[GeneratedRegex(@"^[\p{L}\p{Nl}_][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}\p{Cf}_]*(?:\.[\p{L}\p{Nl}_][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}\p{Cf}_]*)*$")]
|
||||
private static partial Regex NamespacePattern();
|
||||
|
||||
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
|
||||
{
|
||||
//
|
||||
|
||||
@@ -1229,6 +1229,9 @@ ModuleVersion : Version of module to import. If used, ModuleName must represent
|
||||
<data name="UsingStatementNotSupported" xml:space="preserve">
|
||||
<value>This syntax of the 'using' statement is not supported.</value>
|
||||
</data>
|
||||
<data name="InvalidNamespaceValue" xml:space="preserve">
|
||||
<value>The specified namespace in the 'using' statement contains invalid characters.</value>
|
||||
</data>
|
||||
<data name="InformationStream" xml:space="preserve">
|
||||
<value>information stream</value>
|
||||
</data>
|
||||
|
||||
@@ -128,7 +128,10 @@ Describe "Using Namespace" -Tags "CI" {
|
||||
|
||||
ShouldBeParseError "1; using namespace System" UsingMustBeAtStartOfScript 3
|
||||
ShouldBeParseError "using namespace Foo = System" UsingStatementNotSupported 0
|
||||
ShouldBeParseError "using namespace ''" InvalidNamespaceValue 16
|
||||
ShouldBeParseError "using namespace [System]" InvalidNamespaceValue 16
|
||||
ShouldBeParseError "using namespace ',System'" InvalidNamespaceValue 16
|
||||
ShouldBeParseError "using namespace ']System'" InvalidNamespaceValue 16
|
||||
# TODO: add diagnostic (low pri)
|
||||
# ShouldBeParseError "using namespace System; using namespace System" UsingNamespaceAlreadySpecified 24
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user