Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix hyphen-prefixed arguments being split at period#26522

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
yotsuda wants to merge2 commits intoPowerShell:master
base:master
Choose a base branch
Loading
fromyotsuda:fix-issue-6291-hyphen-dot-parsing

Conversation

@yotsuda
Copy link
Contributor

PR Summary

Fix argument parsing for hyphen-prefixed tokens containing periods. Tokens like-foo.bar are now passed as a single argument instead of being incorrectly split into-foo and.bar.

PR Context

Fixes#6291

Also partially addresses the splatting issue described in#6360 (closed due to inactivity, not because it was fixed).

Note: This PR fixes the period (.) splitting issue in splatting, but doesnot fix the colon (:) splitting issue also mentioned in#6360. The colon case requires a different fix in NativeCommandParameterBinder.

The Problem

When passing unquoted arguments that start with a hyphen and contain a period, PowerShell incorrectly splits them at the first period:

functionOut-Argument {$Args }Out-Argument-foo.bar# Actual (before fix): arg[0]: -foo, arg[1]: .bar  (incorrectly split)# Expected:            arg[0]: -foo.bar            (single argument)

This behavior affects many real-world scenarios, particularly when calling external programs with flags like:

  • -DVERSION=1.2.3 (compiler defines)
  • -std=c++20 (compiler standards)
  • -fmodule-file=Hello=Hello.pcm (clang modules)
  • --config=path/to.file (various CLI tools)

Committee Decision

ThePowerShell Committee reviewed this issue and confirmed it is a bug:

"@PowerShell/powershell-committee reviewed this, we believe the treatment of the period as an argument separator is a bug that should be fixed. A bucket 3 breaking change."

Before this fix:

# Simple function to echo argumentsfunctionOut-Argument {$i=0;$Args|ForEach-Object {"arg[$i]:$_";$i++ } }Out-Argument-foo.bar# arg[0]: -foo# arg[1]: .barOut-Argument-foo=bar.baz# arg[0]: -foo=bar# arg[1]: .baz# Even worse with splattingfunctionWrapper { cmd/c echo@Args }Wrapper-foo.bar# Output: -foo .bar (space inserted)

After this fix:

Out-Argument-foo.bar# arg[0]: -foo.barOut-Argument-foo=bar.baz# arg[0]: -foo=bar.baz# Splatting now works correctlyfunctionWrapper { cmd/c echo@Args }Wrapper-foo.bar# Output: -foo.bar

Technical Approach

Root Cause

InScanParameter() method oftokenizer.cs, when the tokenizer encounters a hyphen at the start of a token, it begins scanning for a parameter name. When it encounters a period (.), it terminates the parameter scan and leaves the remaining text (.bar) as a separate token.

This behavior was originally designed for expression mode where. indicates member access (e.g.,$obj.Property). However, in command mode, this special treatment of. causes unintended argument splitting.

Solution

Modified thecase '.' handling inScanParameter() to check if we're in command mode. When in command mode:

  1. The period is recognized as not being part of a valid parameter name
  2. The entire token (including the leading- and everything after the.) is treated as a generic argument
  3. The token is rescanned usingScanGenericToken() which preserves it as a single unit

This approach mirrors the existing handling of quote characters (',") in the same method, which already use the same pattern to treat quoted content as arguments rather than parameters.

case'.':if(InCommandMode()){// Period is never part of a parameter name. Treat the token as an argument.// This handles cases like -foo.bar which should be a single argument.UngetChar();sb.Insert(0,_script[_tokenStart]);// Insert the '-' that we skipped.returnScanGenericToken(sb);}UngetChar();scanning=false;break;

Backward Compatibility Analysis

Why This Change Is Safe

  1. Parameter names cannot contain periods: PowerShell does not allow. in parameter names. Any attempt to declareparam($foo.bar) results in a parse error.

  2. No intentional usage exists: Since-foo.bar cannot match any declared parameter, the current "split at period" behavior is purely accidental. No scripts intentionally rely on-foo.bar being interpreted as-foo with value.bar.

  3. Consistent with user expectations: Users who write-foo.bar expect it to be a single argument (typically for external programs).

  4. Colon syntax remains unchanged: The intentional-param:value syntax continues to work as expected.

Verified Backward Compatibility

The following scenarios were tested and continue to work correctly:

ScenarioStatus
Normal parameter binding (-foo bar)✅ Works
Colon syntax (-foo:bar)✅ Works
Switch parameters (-Verbose)✅ Works
Member access in expressions ($obj.foo)✅ Works
Method calls ('hello'.ToUpper())✅ Works
Negative decimals (-3.14)✅ Works
Range operator (-3..-1)✅ Works
Double-hyphen arguments (--foo.bar)✅ Works (already worked)

Potential Concerns

WG-Engine's Comment

WG-Engine commented:

"WG-Engine looked at this today and agree it is worth pursuing a bug fix for native commands. Attempting to fix this for commands in general, would be too risky."

This PR applies the fix toall commands (not just native commands) because:

  1. Tokenization happens before command resolution: At the tokenizer level, PowerShell doesn't know whether the target is a native command, cmdlet, or function.

  2. No practical difference: Since parameter names cannot contain periods, the "split at period" behavior never provides useful functionality for PowerShell commands either.

  3. Splatting consistency: The fix ensures that$Args and@Args correctly preserve arguments regardless of whether they're ultimately passed to native commands or PowerShell functions.

  4. Extensive testing: All backward compatibility scenarios have been verified with no regressions found.

The PowerShell team should evaluate whether this broader fix is acceptable or if a native-command-only approach is required.

PR Checklist

Test Coverage

Added 25 comprehensive test cases covering:

Basic Cases

  • -foo.bar - single period
  • -foo=bar.baz - equals sign with period

Edge Cases: Multiple and Consecutive Periods

  • -foo..bar - consecutive periods
  • -foo...bar - three consecutive periods
  • -foo.bar.baz - multiple periods
  • -foo=1.2.3.4 - IP-address-like pattern

Edge Cases: Leading and Trailing Periods

  • -.foo - leading period after hyphen
  • -foo. - trailing period

Double Hyphen

  • --foo.bar - GNU-style long option (already worked, included for completeness)

Real-World Use Cases

  • -DVERSION=1.2.3 - compiler define
  • -std=c++20 - compiler standard flag

Splatting

  • @Args with-foo.bar
  • @Args with-foo=bar.baz

Native Commands

  • Direct invocation with period-containing arguments
  • Via splatting

Backward Compatibility

  • Normal parameter binding with space
  • Colon syntax (-foo:bar)
  • Switch parameters
  • Parameter with dot value (-Path .txt)
  • Member access in expression mode
  • Method calls
  • Negative decimal numbers
  • Range operator with negative numbers

Test Results

Context Hyphen-prefixed arguments should not be split at dot  [+] Argument '-foo.bar' should be passed as a single argument  [+] Argument '-foo=bar.baz' should be passed as a single argument  [+] Argument '-foo..bar' with consecutive dots should be passed as a single argument  [+] Argument '-foo...bar' with three consecutive dots should be passed as a single argument  [+] Argument '-foo.bar.baz' with multiple dots should be passed as a single argument  [+] Argument '-foo=1.2.3.4' with multiple dots in value should be passed as a single argument  [+] Argument '-.foo' with leading dot should be passed as a single argument  [+] Argument '-foo.' with trailing dot should be passed as a single argument  [+] Argument '--foo.bar' with double hyphen should be passed as a single argument  [+] Multiple hyphen-prefixed arguments with dots should each be single arguments  [+] Compiler-style argument '-DVERSION=1.2.3' should be passed as a single argument  [+] Compiler-style argument '-std=c++20' should be passed as a single argument  [+] Splatting should preserve hyphen-prefixed arguments with dots  [+] Splatting should preserve arguments with equals and dots  [+] Native command should receive hyphen-prefixed argument with dot as single argument  [+] Native command should receive argument with equals and dot as single argument  [+] Native command via splatting should receive hyphen-prefixed argument with dot as single argument  [+] Normal parameter binding with space should still work  [+] Parameter binding with colon syntax should still work  [+] Switch parameter should not be affected  [+] Parameter with dot value using space should still work  [+] Member access in expression mode should still work  [+] Method call in expression mode should still work  [+] Negative decimal number should still work  [+] Range operator with negative numbers should still workTests Passed: 25/25

Files Changed

  • src/System.Management.Automation/engine/parser/tokenizer.cs - Modified period handling inScanParameter()
  • test/powershell/Language/Parser/Parser.Tests.ps1 - Added comprehensive test coverage

When passing arguments like -foo.bar or -foo=bar.baz, PowerShellincorrectly splits them at the first period. This fix modifies thetokenizer to treat such tokens as single arguments in command mode.FixesPowerShell#6291
@yotsudayotsudaforce-pushed thefix-issue-6291-hyphen-dot-parsing branch fromb179b78 to6423fe1CompareNovember 24, 2025 10:53
@iSazonoviSazonov added the CL-EngineIndicates that a PR should be marked as an engine change in the Change Log labelNov 24, 2025
Copy link
Contributor

CopilotAI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Pull request overview

This PR fixes a tokenizer bug where hyphen-prefixed arguments containing periods (e.g.,-foo.bar,-DVERSION=1.2.3) were incorrectly split at the period character. The fix ensures such arguments are treated as single tokens in command mode, which is critical for passing compiler flags and other command-line arguments to native commands.

Key Changes

  • Modified theScanParameter() method intokenizer.cs to handle periods in command mode by treating the entire token as a generic argument rather than attempting to parse it as a parameter name
  • Added comprehensive test coverage with 25 test cases covering basic functionality, edge cases, real-world scenarios (compiler flags), splatting, native commands, and backward compatibility

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

FileDescription
src/System.Management.Automation/engine/parser/tokenizer.csMoved period handling from the generic case statement to a dedicated case with command mode detection, mirroring the existing pattern used for quote characters
test/powershell/Language/Parser/Parser.Tests.ps1Added comprehensive test context "Hyphen-prefixed arguments should not be split at dot" with 25 test cases validating the fix and ensuring backward compatibility

💡Add Copilot custom instructions for smarter, more guided reviews.Learn how to get started.

@microsoft-github-policy-servicemicrosoft-github-policy-servicebot added the Review - NeededThe PR is being reviewed labelDec 4, 2025
@microsoft-github-policy-service
Copy link
Contributor

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for7 days.
Maintainer, please provide feedback and/or mark it asWaiting on Author

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

Copilot code reviewCopilotCopilot left review comments

@daxian-dbwdaxian-dbwAwaiting requested review from daxian-dbwdaxian-dbw is a code owner

@SeeminglyScienceSeeminglyScienceAwaiting requested review from SeeminglyScienceSeeminglyScience is a code owner

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

CL-EngineIndicates that a PR should be marked as an engine change in the Change LogReview - NeededThe PR is being reviewed

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Parameter parsing/passing: an unquoted argument that starts with a "-" (hyphen) is broken in two at the first "." (period)

2 participants

@yotsuda@iSazonov

[8]ページ先頭

©2009-2025 Movatter.jp