Skip to content

Commit 0746805

Browse files
authored
Handle empty arguments in ArgvToCommandLine (#563)
* Handle empty arguments in ArgvToCommandLine * Format
1 parent 91c0242 commit 0746805

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

include/wil/win32_helpers.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,7 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
10761076
// Somewhat of a hack to avoid the fact that we can't conditionalize a string literal on a template
10771077
static constexpr const CharT empty_string[] = {'\0'};
10781078
static constexpr const CharT single_quote_string[] = {'"', '\0'};
1079+
static constexpr const CharT double_quote_string[] = {'"', '"', '\0'};
10791080
static constexpr const CharT space_string[] = {' ', '\0'};
10801081
static constexpr const CharT quoted_space_string[] = {'"', ' ', '"', '\0'};
10811082

@@ -1093,6 +1094,7 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
10931094
{
10941095
auto currentIndex = index++;
10951096
result += prefix;
1097+
prefix = nextPrefix;
10961098

10971099
const CharT* searchString = initialSearchString;
10981100

@@ -1102,6 +1104,14 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
11021104

11031105
// We need to escape any quotes and CONDITIONALLY any backslashes
11041106
string_view_type str(strRaw);
1107+
if (str.empty() && !forceQuotes)
1108+
{
1109+
// The argument is empty. If we want to preserve it in the command line string, we need to manually insert
1110+
// a pair of quotes since normal parsing won't handle this case
1111+
result.append(double_quote_string);
1112+
continue;
1113+
}
1114+
11051115
size_t pos = 0;
11061116
while (pos < str.size())
11071117
{
@@ -1201,8 +1211,6 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
12011211
{
12021212
result.push_back('"');
12031213
}
1204-
1205-
prefix = nextPrefix;
12061214
}
12071215

12081216
// NOTE: We optimize the force quotes case by including them in the prefix string. We're not appending a prefix

tests/wiTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4207,6 +4207,10 @@ TEST_CASE("WindowsInternalTests::ArgvToCommandLine", "[win32_helpers]")
42074207
R"(test.exe " front" "mid dle" "end " " every where ")",
42084208
R"("test.exe" " front" "mid dle" "end " " every where ")");
42094209

4210+
// Empty arguments should always force quotes
4211+
DoArgvToCommandLineTest(
4212+
{"", "test", "", "foo", "", "", "bar", ""}, R"("" test "" foo "" "" bar "")", R"("" "test" "" "foo" "" "" "bar" "")");
4213+
42104214
// CommandLineToArgvW treats tab characters the same as spaces; test that here
42114215
DoArgvToCommandLineTest(
42124216
{"test.exe", "\tfront", "mid\tdle", "end\t", "\tevery\twhere\t"},

0 commit comments

Comments
 (0)