Validate the value for using namespace during semantic checks to prevent declaring invalid namespaces (#21162)

This commit is contained in:
Dongbo Wang
2024-02-01 09:42:37 -08:00
committed by GitHub
parent 4f02a89906
commit 783fb46e65
3 changed files with 45 additions and 8 deletions
@@ -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
}