Merge pull request #11735 from akallabeth/cmdline-escape-strings

Cmdline escape strings
This commit is contained in:
akallabeth
2025-07-09 11:00:25 +02:00
committed by GitHub
3 changed files with 117 additions and 35 deletions

View File

@@ -4087,8 +4087,43 @@ static BOOL parse_gateway_usage_option(rdpSettings* settings, const char* value)
return freerdp_set_gateway_usage_method(settings, type);
}
static char* unescape(const char* str)
{
char* copy = strdup(str);
if (!copy)
return NULL;
bool escaped = false;
char* dst = copy;
while (*str != '\0')
{
char cur = *str++;
switch (cur)
{
case '\\':
if (!escaped)
{
escaped = true;
continue;
}
// fallthrough
WINPR_FALLTHROUGH
default:
*dst++ = cur;
escaped = false;
break;
}
}
*dst = '\0';
return copy;
}
static BOOL parse_gateway_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_A* arg)
{
char* argval = NULL;
BOOL rc = FALSE;
WINPR_ASSERT(settings);
@@ -4107,9 +4142,10 @@ static BOOL parse_gateway_options(rdpSettings* settings, const COMMAND_LINE_ARGU
for (size_t x = 0; x < count; x++)
{
BOOL validOption = FALSE;
const char* argval = ptr[x];
WINPR_ASSERT(argval);
free(argval);
argval = unescape(ptr[x]);
if (!argval)
goto fail;
const char* gw = option_starts_with("g:", argval);
if (gw)
@@ -4216,6 +4252,7 @@ static BOOL parse_gateway_options(rdpSettings* settings, const COMMAND_LINE_ARGU
rc = TRUE;
fail:
free(argval);
CommandLineParserFree(ptr);
return rc;
}

View File

@@ -495,6 +495,7 @@ static size_t get_element_count(const char* list, BOOL* failed, BOOL fullquoted)
{
size_t count = 0;
int quoted = 0;
bool escaped = false;
BOOL finished = FALSE;
BOOL first = TRUE;
const char* it = list;
@@ -507,7 +508,17 @@ static size_t get_element_count(const char* list, BOOL* failed, BOOL fullquoted)
while (!finished)
{
BOOL nextFirst = FALSE;
switch (*it)
const char cur = *it++;
/* Ignore the symbol that was escaped. */
if (escaped)
{
escaped = false;
continue;
}
switch (cur)
{
case '\0':
if (quoted != 0)
@@ -518,11 +529,18 @@ static size_t get_element_count(const char* list, BOOL* failed, BOOL fullquoted)
}
finished = TRUE;
break;
case '\\':
if (!escaped)
{
escaped = true;
continue;
}
break;
case '\'':
case '"':
if (!fullquoted)
{
int now = is_quoted(*it);
int now = is_quoted(cur) && !escaped;
if (now == quoted)
quoted = 0;
else if (quoted == 0)
@@ -547,7 +565,6 @@ static size_t get_element_count(const char* list, BOOL* failed, BOOL fullquoted)
}
first = nextFirst;
it++;
}
return count + 1;
}
@@ -556,24 +573,40 @@ static char* get_next_comma(char* string, BOOL fullquoted)
{
const char* log = string;
int quoted = 0;
BOOL first = TRUE;
bool first = true;
bool escaped = false;
WINPR_ASSERT(string);
while (TRUE)
{
switch (*string)
char* last = string;
const char cur = *string++;
if (escaped)
{
escaped = false;
continue;
}
switch (cur)
{
case '\0':
if (quoted != 0)
WLog_ERR(TAG, "Invalid quoted argument '%s'", log);
return NULL;
case '\\':
if (!escaped)
{
escaped = true;
continue;
}
break;
case '\'':
case '"':
if (!fullquoted)
{
int now = is_quoted(*string);
int now = is_quoted(cur);
if ((quoted == 0) && !first)
{
WLog_ERR(TAG, "Invalid quoted argument '%s'", log);
@@ -593,14 +626,13 @@ static char* get_next_comma(char* string, BOOL fullquoted)
return NULL;
}
if (quoted == 0)
return string;
return last;
break;
default:
break;
}
first = FALSE;
string++;
}
return NULL;

View File

@@ -21,8 +21,19 @@ static const char* testArgv[] = { "mstsc.exe",
static const char testListAppName[] = "test app name";
static const char* testListArgs[] = {
"a,b,c,d", "a:,\"b:xxx, yyy\",c", "a:,,,b", "a:,\",b", "\"a,b,c,d d d,fff\"", "",
NULL, "'a,b,\",c'", "\"a,b,',c\"", "', a, ', b,c'", "\"a,b,\",c\""
"g:some.gateway.server,u:some\\\"user,p:some\\\"password,d:some\\\"domain,type:auto",
"a,b,c,d",
"a:,\"b:xxx, yyy\",c",
"a:,,,b",
"a:,\",b",
"\"a,b,c,d d d,fff\"",
"",
NULL,
"'a,b,\",c'",
"\"a,b,',c\"",
"', a, ', b,c'",
"\"a,b,\",c\"",
};
static const char* testListArgs1[] = { testListAppName, "a", "b", "c", "d" };
@@ -36,30 +47,32 @@ static const char* testListArgs8[] = { testListAppName, "a", "b", "\"", "c" };
static const char* testListArgs9[] = { testListAppName, "a", "b", "'", "c" };
// static const char* testListArgs10[] = {};
// static const char* testListArgs11[] = {};
static const char* testListArgs12[] = { testListAppName, "g:some.gateway.server",
"u:some\\\"user", "p:some\\\"password",
"d:some\\\"domain", "type:auto" };
static const char** testListArgsResult[] = { testListArgs1,
testListArgs2,
NULL /* testListArgs3 */,
NULL /* testListArgs4 */,
testListArgs5,
testListArgs6,
testListArgs7,
testListArgs8,
testListArgs9,
NULL /* testListArgs10 */,
NULL /* testListArgs11 */ };
static const char** testListArgsResult[] = {
testListArgs12,
testListArgs1,
testListArgs2,
NULL /* testListArgs3 */,
NULL /* testListArgs4 */,
testListArgs5,
testListArgs6,
testListArgs7,
testListArgs8,
testListArgs9,
NULL /* testListArgs10 */,
NULL /* testListArgs11 */
};
static const size_t testListArgsCount[] = {
ARRAYSIZE(testListArgs1),
ARRAYSIZE(testListArgs2),
0 /* ARRAYSIZE(testListArgs3) */,
0 /* ARRAYSIZE(testListArgs4) */,
ARRAYSIZE(testListArgs5),
ARRAYSIZE(testListArgs6),
ARRAYSIZE(testListArgs7),
ARRAYSIZE(testListArgs8),
ARRAYSIZE(testListArgs9),
0 /* ARRAYSIZE(testListArgs10) */,
0 /* ARRAYSIZE(testListArgs11) */
ARRAYSIZE(testListArgs12), ARRAYSIZE(testListArgs1),
ARRAYSIZE(testListArgs2), 0 /* ARRAYSIZE(testListArgs3) */,
0 /* ARRAYSIZE(testListArgs4) */, ARRAYSIZE(testListArgs5),
ARRAYSIZE(testListArgs6), ARRAYSIZE(testListArgs7),
ARRAYSIZE(testListArgs8), ARRAYSIZE(testListArgs9),
0 /* ARRAYSIZE(testListArgs10) */, 0 /* ARRAYSIZE(testListArgs11) */
};
static BOOL checkResult(size_t index, char** actual, size_t actualCount)