BUG: Argument parsers do not always remove double quotes from around an argument that has no spaces.

This commit is contained in:
Brad King 2003-07-03 18:33:53 -04:00
parent f22a4a908d
commit 33566642a0

View File

@ -442,11 +442,12 @@ void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
if(command) if(command)
{ {
/* We need to construct a single string representing the command /* We need to construct a single string representing the command
and its arguments. We will surround each argument with and its arguments. We will surround each argument containing
double-quotes so it can contain spaces. We need to escape spaces with double-quotes. Inside a double-quoted argument, we
double-quotes and all backslashes before them. We also need to need to escape double-quotes and all backslashes before them.
escape backslashes at the end of an argument because they come We also need to escape backslashes at the end of an argument
before the closing double-quote for the argument. */ because they come before the closing double-quote for the
argument. */
char* cmd; char* cmd;
char const* const* arg; char const* const* arg;
int length = 0; int length = 0;
@ -456,38 +457,56 @@ void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
/* Keep track of how many backslashes have been encountered in a /* Keep track of how many backslashes have been encountered in a
row in this argument. */ row in this argument. */
int backslashes = 0; int backslashes = 0;
int spaces = 0;
const char* c; const char* c;
/* Add the length of the argument, plus 3 for the double quotes /* Scan the string for spaces. If there are no spaces, we can
and space separating the arguments. */ pass the argument verbatim. */
length += (int)strlen(*arg) + 3;
/* Scan the string to find characters that need escaping. */
for(c=*arg; *c; ++c) for(c=*arg; *c; ++c)
{ {
if(*c == '\\') if(*c == ' ' || *c == '\t')
{ {
/* Found a backslash. It may need to be escaped later. */ spaces = 1;
++backslashes; break;
}
else if(*c == '"')
{
/* Found a double-quote. We need to escape it and all
immediately preceding backslashes. */
length += backslashes + 1;
backslashes = 0;
}
else
{
/* Found another character. This eliminates the possibility
that any immediately preceding backslashes will be
escaped. */
backslashes = 0;
} }
} }
/* We need to escape all ending backslashes. */ /* Add the length of the argument, plus 1 for the space
length += backslashes; separating the arguments. */
length += (int)strlen(*arg) + 1;
if(spaces)
{
/* Add 2 for double quotes since spaces are present. */
length += 2;
/* Scan the string to find characters that need escaping. */
for(c=*arg; *c; ++c)
{
if(*c == '\\')
{
/* Found a backslash. It may need to be escaped later. */
++backslashes;
}
else if(*c == '"')
{
/* Found a double-quote. We need to escape it and all
immediately preceding backslashes. */
length += backslashes + 1;
backslashes = 0;
}
else
{
/* Found another character. This eliminates the possibility
that any immediately preceding backslashes will be
escaped. */
backslashes = 0;
}
}
/* We need to escape all ending backslashes. */
length += backslashes;
}
} }
/* Allocate enough space for the command. We do not need an extra /* Allocate enough space for the command. We do not need an extra
@ -502,65 +521,88 @@ void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
/* Keep track of how many backslashes have been encountered in a /* Keep track of how many backslashes have been encountered in a
row in an argument. */ row in an argument. */
int backslashes = 0; int backslashes = 0;
int spaces = 0;
const char* c; const char* c;
/* Scan the string for spaces. If there are no spaces, we can
pass the argument verbatim. */
for(c=*arg; *c; ++c)
{
if(*c == ' ' || *c == '\t')
{
spaces = 1;
break;
}
}
/* Add the separating space if this is not the first argument. */ /* Add the separating space if this is not the first argument. */
if(arg != command) if(arg != command)
{ {
*cmd++ = ' '; *cmd++ = ' ';
} }
/* Add the opening double-quote for this argument. */ if(spaces)
*cmd++ = '"';
/* Add the characters of the argument, possibly escaping them. */
for(c=*arg; *c; ++c)
{ {
if(*c == '\\') /* Add the opening double-quote for this argument. */
*cmd++ = '"';
/* Add the characters of the argument, possibly escaping them. */
for(c=*arg; *c; ++c)
{ {
/* Found a backslash. It may need to be escaped later. */ if(*c == '\\')
++backslashes;
*cmd++ = '\\';
}
else if(*c == '"')
{
/* Add enough backslashes to escape any that preceded the
double-quote. */
while(backslashes > 0)
{ {
--backslashes; /* Found a backslash. It may need to be escaped later. */
++backslashes;
*cmd++ = '\\'; *cmd++ = '\\';
} }
else if(*c == '"')
{
/* Add enough backslashes to escape any that preceded the
double-quote. */
while(backslashes > 0)
{
--backslashes;
*cmd++ = '\\';
}
/* Add the backslash to escape the double-quote. */ /* Add the backslash to escape the double-quote. */
*cmd++ = '\\'; *cmd++ = '\\';
/* Add the double-quote itself. */ /* Add the double-quote itself. */
*cmd++ = '"'; *cmd++ = '"';
}
else
{
/* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. Add the
character. */
backslashes = 0;
*cmd++ = *c;
}
} }
else
/* Add enough backslashes to escape any trailing ones. */
while(backslashes > 0)
{
--backslashes;
*cmd++ = '\\';
}
/* Add the closing double-quote for this argument. */
*cmd++ = '"';
}
else
{
/* No spaces. Add the argument verbatim. */
for(c=*arg; *c; ++c)
{ {
/* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. Add the
character. */
backslashes = 0;
*cmd++ = *c; *cmd++ = *c;
} }
} }
/* Add enough backslashes to escape any trailing ones. */
while(backslashes > 0)
{
--backslashes;
*cmd++ = '\\';
}
/* Add the opening double-quote for this argument. */
*cmd++ = '"';
} }
/* Add the terminating null character to the command line. */ /* Add the terminating null character to the command line. */
*cmd++ = 0; *cmd = 0;
} }
} }