CMD inconsistent parsing behavior when the /C argument is present #13045

Closed
opened 2026-01-31 03:32:11 +00:00 by claunia · 6 comments
Owner

Originally created by @snake-4 on GitHub (Mar 15, 2021).

Environment

Windows build number: Microsoft Windows [Version 10.0.19042.867]
Windows Terminal version (if applicable): N/A

Any other software? A simple test app written in C.

Steps to reproduce

Compile the following C program with any compiler of your choice.

#include <stdio.h>
#include <Windows.h>

int main(int argc, char* argv[])
{
	HANDLE hComPort = CreateFileW(L"\\\\.\\COM9", GENERIC_READ | GENERIC_WRITE, 0, NULL,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	printf("Can open: %s\nGetLastError(): %x", (hComPort == INVALID_HANDLE_VALUE ? "NO" : "YES"), GetLastError());
}

Now run the program like this cmd /C "testprog COM9" and it won't be able to open the port and the last error will be 5.
But if you run the program without any arguments, it will be able to open the port just fine. I think what's happening here is that the cmd is somehow opening the port itself.

Expected behavior

Running the program mentioned above with a command like this cmd /C "testprog COM9" should be able to open the port.

Actual behavior

There are two possible outcomes for every test here, either it fails and the last error gets set to 5 or it works fine.
Note: I've performed the following test cases multiple times and tried to restart my computer and each time the outcome was the same.

cmd /C "testprog dummyarg1" works
cmd /C "testprog dummyarg1 COM9" works
cmd /C "testprog dummyarg1 "COM9"" fails
cmd /C "testprog -dummyarg1 COM9" fails

cmd /C "testprog COM9" fails
testprog COM9 works

cmd /e off /C "testprog COM9" fails (*)
cmd /e off /e off /C "testprog COM9" works (*)
cmd /v off /C "testprog COM9" fails (*)
cmd /v off /v off /C "testprog COM9" works (*)

(*) These starred test cases are the most interesting ones because I think they clearly indicate a problem with the cmd's parsing.

Originally created by @snake-4 on GitHub (Mar 15, 2021). <!-- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING: 1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement. 2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement. 3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number). 4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement. 5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement. All good? Then proceed! --> <!-- This bug tracker is monitored by Windows Terminal development team and other technical folks. **Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**. Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue. If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link. Please use this form and describe your issue, concisely but precisely, with as much detail as possible. --> # Environment ```none Windows build number: Microsoft Windows [Version 10.0.19042.867] Windows Terminal version (if applicable): N/A Any other software? A simple test app written in C. ``` # Steps to reproduce Compile the following C program with any compiler of your choice. ```C #include <stdio.h> #include <Windows.h> int main(int argc, char* argv[]) { HANDLE hComPort = CreateFileW(L"\\\\.\\COM9", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); printf("Can open: %s\nGetLastError(): %x", (hComPort == INVALID_HANDLE_VALUE ? "NO" : "YES"), GetLastError()); } ``` Now run the program like this `cmd /C "testprog COM9"` and it won't be able to open the port and the last error will be `5`. But if you run the program without any arguments, it will be able to open the port just fine. I think what's happening here is that the cmd is somehow opening the port itself. <!-- A description of how to trigger this bug. --> # Expected behavior Running the program mentioned above with a command like this `cmd /C "testprog COM9"` should be able to open the port. <!-- A description of what you're expecting, possibly containing screenshots or reference material. --> # Actual behavior There are two possible outcomes for every test here, either it fails and the last error gets set to `5` or it works fine. Note: I've performed the following test cases multiple times and tried to restart my computer and each time the outcome was the same. `cmd /C "testprog dummyarg1"` works `cmd /C "testprog dummyarg1 COM9"` works `cmd /C "testprog dummyarg1 "COM9""` fails `cmd /C "testprog -dummyarg1 COM9"` fails `cmd /C "testprog COM9"` fails `testprog COM9` works `cmd /e off /C "testprog COM9"` fails (\*) `cmd /e off /e off /C "testprog COM9"` works (\*) `cmd /v off /C "testprog COM9"` fails (\*) `cmd /v off /v off /C "testprog COM9"` works (\*) (*) These starred test cases are the most interesting ones because I think they clearly indicate a problem with the cmd's parsing. <!-- What's actually happening? -->
claunia added the Needs-TriageNeeds-Tag-FixNeeds-AttentionProduct-Cmd.exe labels 2026-01-31 03:32:11 +00:00
Author
Owner

@jdebp commented on GitHub (Mar 21, 2021):

cmd problems are not bugs in Windows Terminal, and this is not even a cmd problem in the first place. Such odd behaviours of USB serial port devices, as com9 undoubtedly is, have been noted by people for about 10 years now. See https://stackoverflow.com/q/2948428/340790 just for starters.

@jdebp commented on GitHub (Mar 21, 2021): `cmd` problems are not bugs in Windows Terminal, and this is not even a `cmd` problem in the first place. Such odd behaviours of USB serial port devices, as `com9` undoubtedly is, have been noted by people for about 10 years now. See https://stackoverflow.com/q/2948428/340790 just for starters.
Author
Owner

@snake-4 commented on GitHub (Mar 21, 2021):

cmd problems are not bugs in Windows Terminal, and this is not even a cmd problem in the first place. Such odd behaviours of USB serial port devices, as com9 undoubtedly is, have been noted by people for about 10 years now. See https://stackoverflow.com/q/2948428/340790 just for starters.

I know this is not a Windows Terminal bug, the fact that Product-Cmd.exe tag exists leads me to believe that this is the right place to report this issue. Besides, the behavior is still the same if I call CloseHandle before program exit. I think this is definitely a cmd issue as the program does nothing with the passed arguments at all and the last four test cases where passing an extra argument to the cmd should not change a single thing about the behavior of the program that is ran. Please check the other test cases and their results that I've provided as well and as I've already said, I've performed these tests multiple times and the results are consistent. If the results weren't consistent I would also say that this could be a driver issue. I'm almost certain that the driver is not changing it's behavior depending on the command line of the parent process of the program that is opening the serial port and this is a cmd issue.

@snake-4 commented on GitHub (Mar 21, 2021): > > > `cmd` problems are not bugs in Windows Terminal, and this is not even a `cmd` problem in the first place. Such odd behaviours of USB serial port devices, as `com9` undoubtedly is, have been noted by people for about 10 years now. See https://stackoverflow.com/q/2948428/340790 just for starters. I know this is not a Windows Terminal bug, the fact that `Product-Cmd.exe` tag exists leads me to believe that this is the right place to report this issue. Besides, the behavior is still the same if I call `CloseHandle` before program exit. I think this is definitely a cmd issue as the program does nothing with the passed arguments at all and the last four test cases where passing an extra argument to the **cmd** should not change a single thing about the behavior of the program that is ran. Please check the other test cases and their results that I've provided as well and as I've already said, I've performed these tests multiple times and the results are consistent. If the results weren't consistent I would also say that this could be a driver issue. I'm almost certain that the driver is not changing it's behavior depending on the command line of the parent process of the program that is opening the serial port and this is a cmd issue.
Author
Owner

@zadjii-msft commented on GitHub (Mar 22, 2021):

Technically yes, our team owns cmd.exe, but cmd.exe is in super-critical-only-bugfix-mode. We're absolutely not touching that code, even for simple bugfixes. Cmd.exe has worked the way it works for decades, and it turns out that there are lots of enterprises out there that rely on each and every weird bug that exists in it.

Is this a new bug you're seeing? Or one that repros on older versions of Windows as well?

@zadjii-msft commented on GitHub (Mar 22, 2021): Technically yes, our team owns cmd.exe, but cmd.exe is in super-critical-only-bugfix-mode. We're absolutely not touching that code, even for simple bugfixes. Cmd.exe has worked the way it works for decades, and it turns out that there are lots of enterprises out there that rely on each and every weird bug that exists in it. Is this a new bug you're seeing? Or one that repros on older versions of Windows as well?
Author
Owner

@snake-4 commented on GitHub (Mar 22, 2021):

Alright so I couldn't reproduce the bug on any version of Windows in VM environment but it turns out that it was caused by the Windows Defender. Windows Defender with real-time protection enabled opens the port when it sees it in the arguments of the cmd.exe for a short amount of time but long enough to not let the program to open the port immediately after it starts. Not sure why Defender wasn't doing this before and is now causing this issue but adding a small delay before the CreateFile or adding the cmd.exe to the excluded files in Defender fixes the problem. Sorry for the inconvenience. I'll close this issue now.

@snake-4 commented on GitHub (Mar 22, 2021): Alright so I couldn't reproduce the bug on any version of Windows in VM environment but it turns out that it was caused by the Windows Defender. Windows Defender with real-time protection enabled opens the port when it sees it in the arguments of the cmd.exe for a short amount of time but long enough to not let the program to open the port immediately after it starts. Not sure why Defender wasn't doing this before and is now causing this issue but adding a small delay before the CreateFile or adding the cmd.exe to the excluded files in Defender fixes the problem. Sorry for the inconvenience. I'll close this issue now.
Author
Owner

@DHowett commented on GitHub (Mar 22, 2021):

Glad you figured it out! Defender has even been known to go so far as to read command line arguments to determine whether they are files to be scanned.

@DHowett commented on GitHub (Mar 22, 2021): Glad you figured it out! Defender has even been known to go so far as to read _command line arguments_ to determine whether they are files to be scanned.
Author
Owner

@KalleOlaviNiemitalo commented on GitHub (Mar 23, 2021):

COM9 is a reserved file name, but perhaps Defender is taking a precaution in case \DosDevices\COM9 might be an Object Manager symbolic link to a regular file. I wonder if the serial-port driver could resolve the conflict by supporting oplocks as if it were a file system.

@KalleOlaviNiemitalo commented on GitHub (Mar 23, 2021): COM9 is a reserved file name, but perhaps Defender is taking a precaution in case \DosDevices\COM9 might be an Object Manager symbolic link to a regular file. I wonder if the serial-port driver could resolve the conflict by supporting oplocks as if it were a file system.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#13045