mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-15 16:40:12 -06:00
Fix a crash during commandline handoff (#19096)
The crash occurs because WinRT `abort()`s when it encounters a `std::wstring_view` without null-terminator. Closes #19093 ## Validation Steps Performed * Set `wtd` as the default terminal * Launch `cmd` * Launch `wtd` * 2 windows ✅
This commit is contained in:
parent
4500d42831
commit
ac07afebcb
@ -49,7 +49,7 @@ static std::vector<winrt::hstring> commandlineToArgArray(const wchar_t* commandL
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the length of a double-null encoded string *excluding* the trailing double-null character.
|
// Returns the length of a double-null encoded string *excluding* the trailing double-null character.
|
||||||
static std::wstring_view stringFromDoubleNullTerminated(const wchar_t* beg)
|
static wil::zwstring_view stringFromDoubleNullTerminated(const wchar_t* beg)
|
||||||
{
|
{
|
||||||
auto end = beg;
|
auto end = beg;
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ static std::wstring_view stringFromDoubleNullTerminated(const wchar_t* beg)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
return { beg, end };
|
return { beg, gsl::narrow_cast<size_t>(end - beg) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends an uint32_t to a byte vector.
|
// Appends an uint32_t to a byte vector.
|
||||||
@ -78,36 +78,39 @@ static const uint8_t* deserializeUint32(const uint8_t* it, const uint8_t* end, u
|
|||||||
return it + sizeof(uint32_t);
|
return it + sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an uint32_t length prefix, followed by the string data, to the output vector.
|
// Writes a null-terminated string to `out`: A uint32_t length prefix,
|
||||||
static void serializeString(std::vector<uint8_t>& out, std::wstring_view str)
|
// *including null byte*, followed by the string data, followed by the null-terminator.
|
||||||
|
static void serializeString(std::vector<uint8_t>& out, wil::zwstring_view str)
|
||||||
{
|
{
|
||||||
const auto ptr = reinterpret_cast<const uint8_t*>(str.data());
|
const auto ptr = reinterpret_cast<const uint8_t*>(str.data());
|
||||||
const auto len = gsl::narrow<uint32_t>(str.size());
|
const auto len = str.size() + 1;
|
||||||
serializeUint32(out, len);
|
serializeUint32(out, gsl::narrow<uint32_t>(len));
|
||||||
out.insert(out.end(), ptr, ptr + len * sizeof(wchar_t));
|
out.insert(out.end(), ptr, ptr + len * sizeof(wchar_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses the next string from the input iterator. Performs bounds-checks.
|
// Counter-part to `serializeString`. Performs bounds-checks.
|
||||||
// Returns an iterator that points past it.
|
// Returns an iterator that points past it.
|
||||||
static const uint8_t* deserializeString(const uint8_t* it, const uint8_t* end, std::wstring_view& str)
|
static const uint8_t* deserializeString(const uint8_t* it, const uint8_t* end, wil::zwstring_view& str)
|
||||||
{
|
{
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
it = deserializeUint32(it, end, len);
|
it = deserializeUint32(it, end, len);
|
||||||
|
|
||||||
if (static_cast<size_t>(end - it) < len * sizeof(wchar_t))
|
const auto bytes = static_cast<size_t>(len) * sizeof(wchar_t);
|
||||||
|
|
||||||
|
if (bytes == 0 || static_cast<size_t>(end - it) < bytes)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Not enough data for string content");
|
throw std::out_of_range("Not enough data for string content");
|
||||||
}
|
}
|
||||||
|
|
||||||
str = { reinterpret_cast<const wchar_t*>(it), len };
|
str = { reinterpret_cast<const wchar_t*>(it), len - 1 };
|
||||||
return it + len * sizeof(wchar_t);
|
return it + bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Handoff
|
struct Handoff
|
||||||
{
|
{
|
||||||
std::wstring_view args;
|
wil::zwstring_view args;
|
||||||
std::wstring_view env;
|
wil::zwstring_view env;
|
||||||
std::wstring_view cwd;
|
wil::zwstring_view cwd;
|
||||||
uint32_t show;
|
uint32_t show;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -612,7 +615,7 @@ void WindowEmperor::_dispatchCommandline(winrt::TerminalApp::CommandlineArgs arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowEmperor::_dispatchCommandlineCommon(winrt::array_view<const winrt::hstring> args, std::wstring_view currentDirectory, std::wstring_view envString, uint32_t showWindowCommand)
|
void WindowEmperor::_dispatchCommandlineCommon(winrt::array_view<const winrt::hstring> args, wil::zwstring_view currentDirectory, wil::zwstring_view envString, uint32_t showWindowCommand)
|
||||||
{
|
{
|
||||||
winrt::TerminalApp::CommandlineArgs c;
|
winrt::TerminalApp::CommandlineArgs c;
|
||||||
c.Commandline(args);
|
c.Commandline(args);
|
||||||
@ -929,8 +932,7 @@ LRESULT WindowEmperor::_messageHandler(HWND window, UINT const message, WPARAM c
|
|||||||
if (const auto cds = reinterpret_cast<COPYDATASTRUCT*>(lParam); cds->dwData == TERMINAL_HANDOFF_MAGIC)
|
if (const auto cds = reinterpret_cast<COPYDATASTRUCT*>(lParam); cds->dwData == TERMINAL_HANDOFF_MAGIC)
|
||||||
{
|
{
|
||||||
const auto handoff = deserializeHandoffPayload(static_cast<const uint8_t*>(cds->lpData), static_cast<const uint8_t*>(cds->lpData) + cds->cbData);
|
const auto handoff = deserializeHandoffPayload(static_cast<const uint8_t*>(cds->lpData), static_cast<const uint8_t*>(cds->lpData) + cds->cbData);
|
||||||
const winrt::hstring args{ handoff.args };
|
const auto argv = commandlineToArgArray(handoff.args.c_str());
|
||||||
const auto argv = commandlineToArgArray(args.c_str());
|
|
||||||
_dispatchCommandlineCommon(argv, handoff.cwd, handoff.env, handoff.show);
|
_dispatchCommandlineCommon(argv, handoff.cwd, handoff.env, handoff.show);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -52,7 +52,7 @@ private:
|
|||||||
void _summonAllWindows() const;
|
void _summonAllWindows() const;
|
||||||
void _dispatchSpecialKey(const MSG& msg) const;
|
void _dispatchSpecialKey(const MSG& msg) const;
|
||||||
void _dispatchCommandline(winrt::TerminalApp::CommandlineArgs args);
|
void _dispatchCommandline(winrt::TerminalApp::CommandlineArgs args);
|
||||||
void _dispatchCommandlineCommon(winrt::array_view<const winrt::hstring> args, std::wstring_view currentDirectory, std::wstring_view envString, uint32_t showWindowCommand);
|
void _dispatchCommandlineCommon(winrt::array_view<const winrt::hstring> args, wil::zwstring_view currentDirectory, wil::zwstring_view envString, uint32_t showWindowCommand);
|
||||||
safe_void_coroutine _dispatchCommandlineCurrentDesktop(winrt::TerminalApp::CommandlineArgs args);
|
safe_void_coroutine _dispatchCommandlineCurrentDesktop(winrt::TerminalApp::CommandlineArgs args);
|
||||||
LRESULT _messageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam) noexcept;
|
LRESULT _messageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam) noexcept;
|
||||||
void _createMessageWindow(const wchar_t* className);
|
void _createMessageWindow(const wchar_t* className);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user