-
Notifications
You must be signed in to change notification settings - Fork 8.5k
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug Report: The conhost command line is not properly escaped #1090
Comments
I'm inclined to think that this will be solved when we switch to the real conpty API. Right now, we're using the legacy method of launching conhost.exe as a conpty, and requesting that conhost launches the process on behalf of us. This results in the commandline needing to be escaped twice like this, which is pretty painful. We have some work planned to switch the Terminal back to using the API directly. When we make that change, then we won't need to double-escape the commandline, we'll just use the commandline to CreateProcess the process directly, and we'll attach that process to a conpty. |
@zadjii-msft is totally right. I'll file up with a Deliverable to use |
@zadjii-msft @DHowett-MSFT Thanks. Using the conpty API is correct, but I think conhost still needs to solve this problem. |
It will probably solve this problem by getting 100% out of the business of accepting commandlines of other applications to spawn as arguments. |
@DHowett-MSFT Good |
(adding some notes from a related email thread:) I'm hacking some integration between Windows Terminal and a new VS2019 feature but this doesn't work (at least not obviously/easily/with normal json)
Okay, so the problem is in conhost. When we’re starting conhost for the Terminal, we get the commandline already broken up into args. Conhost then takes all those args, and joins them with spaces, to call CreateProcess again, to launch the client app. Because CreateProcess has already tried to help here while launching `conhost -- `, it already grouped the entire last arg as a single arg. So, conhost never knew that last arg had quotes around it. If you once again escape the quotes around the path, it should work:
|
@zadjii-msft I still recommend reassembling the command line arguments for use by CreateProcess using the previous |
@zadjii-msft @DHowett-MSFT |
Unfortunately, Windows UCRT's Can someone feedback this question to the ucrt team? See: // Converts a main()-style argv arguments vector into a command line. On success,
// returns a pointer to the newly constructed arguments block; the caller is
// responsible for freeing the string. On failure, returns null and sets errno.
template <typename Character>
static errno_t __cdecl construct_command_line(
Character const* const* const argv,
Character** const command_line_result
) throw()
{
typedef __crt_char_traits<Character> traits;
*command_line_result = nullptr;
// Compute the number of bytes required to store the arguments in argv in a
// command line string (including spaces between arguments and a terminator):
size_t const command_line_count = [&]
{
size_t n = 0;
for (Character const* const* it = argv; *it; n += traits::tcslen(*it++) + 1) { }
// If there were no arguments, return 1 so that we can return an empty
// string:
return __max(n, 1);
}();
__crt_unique_heap_ptr<Character> command_line(_calloc_crt_t(Character, command_line_count));
if (!command_line)
{
__acrt_errno_map_os_error(ERROR_NOT_ENOUGH_MEMORY);
return errno = ENOMEM;
}
Character const* const* source_it = argv;
Character* result_it = command_line.get();
// If there are no arguments, just return the empty string:
if (*source_it == '\0')
{
*command_line_result = command_line.detach();
return 0;
}
// Copy the arguments, separated by spaces:
while (*source_it != '\0')
{
_ERRCHECK(traits::tcscpy_s(result_it, command_line_count - (result_it - command_line.get()), *source_it));
result_it += traits::tcslen(*source_it);
*result_it++ = ' ';
++source_it;
}
// Replace the last space with a terminator:
result_it[-1] = '\0';
*command_line_result = command_line.detach();
return 0;
}
|
🎉This issue was addressed in #1815, which has now been successfully released as Handy links: |
Environment
Today I modified the Windows Terminal configuration file and wanted to create a Pwsh with the emoji title. However, I encountered some confusion in this process. I checked the task manager and found that conhost did not escape when the process was started, causing the command line to parse the exception.
Steps to reproduce
Expected behavior
I need to start pwsh by the following command line (note that the following command line is in cmd, or you can start pwsh normally using CreateProcessW.)
Here is the Windows Terminal configuration file (the command line has been properly escaped):
Actual behavior
As expected, Pwsh should set the title correctly, but pwsh reported the error:

Let's take a look at the command line:
When you see the red line, the command line that pwsh starts is incorrect, and when you start conhost, the command line is still correct!
Currently I have found a suspicious code, most likely this code caused an error:
terminal/src/host/ConsoleArguments.cpp
Lines 263 to 288 in 71e19cd
In this code, command line composition is simply a simple connection rather than a concatenated string. If the string contains spaces, this will result in an incorrect command line.
Below is a code for the command line escaping, which may be useful:
The text was updated successfully, but these errors were encountered: