- Added "\c" support to ParseCommandLine() when it parses quoted strings.

- Fixed: When changing your name from the menu, you got an extra " appended
  to your name if it ended with a backslash.
- Added escape sequences for user info strings, so now they can contain
  embedded backslashes.
- Fixed an array-out-of-bounds access when drawing the player setup menu with
  an invalid team number.


SVN r598 (trunk)
This commit is contained in:
Randy Heit 2007-12-15 03:27:40 +00:00
parent 089c2dab48
commit 8d5402cec2
5 changed files with 123 additions and 37 deletions

View file

@ -1,3 +1,12 @@
December 14, 2007
- Added "\c" support to ParseCommandLine() when it parses quoted strings.
- Fixed: When changing your name from the menu, you got an extra " appended
to your name if it ended with a backslash.
- Added escape sequences for user info strings, so now they can contain
embedded backslashes.
- Fixed an array-out-of-bounds access when drawing the player setup menu with
an invalid team number.
December 10, 2007 December 10, 2007
- Fixed: The MAPINFO flags that control jumping, crouching, and freelook, - Fixed: The MAPINFO flags that control jumping, crouching, and freelook,
rather than overriding the dmflags values, actually overwrote the dmflags rather than overriding the dmflags values, actually overwrote the dmflags

View file

@ -718,8 +718,11 @@ void AddCommandString (char *cmd, int keynum)
// to point to a buffer large enough to hold all the arguments. The // to point to a buffer large enough to hold all the arguments. The
// return value is the necessary size of this buffer. // return value is the necessary size of this buffer.
// //
// Special processing: Inside quoted strings, \" becomes just " // Special processing:
// $<cvar> is replaced by the contents of <cvar> // Inside quoted strings, \" becomes just "
// \\ becomes just \
// \c becomes just TEXTCOLOR_ESCAPE
// $<cvar> is replaced by the contents of <cvar>
static long ParseCommandLine (const char *args, int *argc, char **argv) static long ParseCommandLine (const char *args, int *argc, char **argv)
{ {
@ -759,6 +762,14 @@ static long ParseCommandLine (const char *args, int *argc, char **argv)
{ {
stuff = '\"', args++; stuff = '\"', args++;
} }
else if (stuff == '\\' && *args == '\\')
{
args++;
}
else if (stuff == '\\' && *args == 'c')
{
stuff = TEXTCOLOR_ESCAPE, args++;
}
else if (stuff == '\"') else if (stuff == '\"')
{ {
stuff = 0; stuff = 0;

View file

@ -110,6 +110,55 @@ static const char *UserInfoStrings[] =
NULL NULL
}; };
// Replace \ with %/ and % with %%
FString D_EscapeUserInfo (const char *str)
{
FString ret;
for (; *str != '\0'; ++str)
{
if (*str == '\\')
{
ret << '%' << '/';
}
else if (*str == '%')
{
ret << '%' << '%';
}
else
{
ret << *str;
}
}
return ret;
}
// Replace %/ with \ and %% with %
FString D_UnescapeUserInfo (const char *str, size_t len)
{
const char *end = str + len;
FString ret;
while (*str != '\0' && str < end)
{
if (*str == '%')
{
if (*(str + 1) == '/')
{
ret << '\\';
str += 2;
continue;
}
else if (*(str + 1) == '%')
{
str++;
}
}
ret << *str++;
}
return ret;
}
int D_GenderToInt (const char *gender) int D_GenderToInt (const char *gender)
{ {
if (!stricmp (gender, "female")) if (!stricmp (gender, "female"))
@ -339,6 +388,7 @@ void D_SetupUserInfo ()
void D_UserInfoChanged (FBaseCVar *cvar) void D_UserInfoChanged (FBaseCVar *cvar)
{ {
UCVarValue val; UCVarValue val;
FString escaped_val;
char foo[256]; char foo[256];
if (cvar == &autoaim) if (cvar == &autoaim)
@ -356,10 +406,11 @@ void D_UserInfoChanged (FBaseCVar *cvar)
} }
val = cvar->GetGenericRep (CVAR_String); val = cvar->GetGenericRep (CVAR_String);
if (4 + strlen (cvar->GetName ()) + strlen (val.String) > 256) escaped_val = D_EscapeUserInfo(val.String);
if (4 + strlen(cvar->GetName()) + escaped_val.Len() > 256)
I_Error ("User info descriptor too big"); I_Error ("User info descriptor too big");
sprintf (foo, "\\%s\\%s", cvar->GetName (), val.String); sprintf (foo, "\\%s\\%s", cvar->GetName(), escaped_val.GetChars());
Net_WriteByte (DEM_UINFCHANGED); Net_WriteByte (DEM_UINFCHANGED);
Net_WriteString (foo); Net_WriteString (foo);
@ -518,17 +569,18 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
"\\stillbob\\%g" "\\stillbob\\%g"
"\\playerclass\\%s" "\\playerclass\\%s"
, ,
info->netname, D_EscapeUserInfo(info->netname).GetChars(),
(double)info->aimdist / (float)ANGLE_1, (double)info->aimdist / (float)ANGLE_1,
RPART(info->color), GPART(info->color), BPART(info->color), RPART(info->color), GPART(info->color), BPART(info->color),
skins[info->skin].name, info->team, D_EscapeUserInfo(skins[info->skin].name).GetChars(),
info->team,
info->gender == GENDER_FEMALE ? "female" : info->gender == GENDER_FEMALE ? "female" :
info->gender == GENDER_NEUTER ? "other" : "male", info->gender == GENDER_NEUTER ? "other" : "male",
info->neverswitch, info->neverswitch,
(float)(info->MoveBob) / 65536.f, (float)(info->MoveBob) / 65536.f,
(float)(info->StillBob) / 65536.f, (float)(info->StillBob) / 65536.f,
info->PlayerClass == -1 ? "Random" : info->PlayerClass == -1 ? "Random" :
type->Meta.GetMetaString (APMETA_DisplayName) D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars()
); );
} }
else else
@ -546,10 +598,10 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
"\\%g" // stillbob "\\%g" // stillbob
"\\%s" // playerclass "\\%s" // playerclass
, ,
info->netname, D_EscapeUserInfo(info->netname).GetChars(),
(double)info->aimdist / (float)ANGLE_1, (double)info->aimdist / (float)ANGLE_1,
RPART(info->color), GPART(info->color), BPART(info->color), RPART(info->color), GPART(info->color), BPART(info->color),
skins[info->skin].name, D_EscapeUserInfo(skins[info->skin].name).GetChars(),
info->team, info->team,
info->gender == GENDER_FEMALE ? "female" : info->gender == GENDER_FEMALE ? "female" :
info->gender == GENDER_NEUTER ? "other" : "male", info->gender == GENDER_NEUTER ? "other" : "male",
@ -557,7 +609,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
(float)(info->MoveBob) / 65536.f, (float)(info->MoveBob) / 65536.f,
(float)(info->StillBob) / 65536.f, (float)(info->StillBob) / 65536.f,
info->PlayerClass == -1 ? "Random" : info->PlayerClass == -1 ? "Random" :
type->Meta.GetMetaString (APMETA_DisplayName) D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars()
); );
} }
} }
@ -568,9 +620,9 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
void D_ReadUserInfoStrings (int i, BYTE **stream, bool update) void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
{ {
userinfo_t *info = &players[i].userinfo; userinfo_t *info = &players[i].userinfo;
char *ptr = *((char **)stream); const char *ptr = *((const char **)stream);
char *breakpt; const char *breakpt;
char *value; FString value;
bool compact; bool compact;
int infotype = -1; int infotype = -1;
@ -583,25 +635,37 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
{ {
for (;;) for (;;)
{ {
breakpt = strchr (ptr, '\\'); int j;
if (breakpt != NULL) breakpt = strchr (ptr, '\\');
*breakpt = 0;
if (compact) if (compact)
{ {
value = ptr; value = D_UnescapeUserInfo(ptr, breakpt - ptr);
infotype++; infotype++;
} }
else if (breakpt != NULL) else
{ {
value = breakpt + 1; assert(breakpt != NULL);
if ( (breakpt = strchr (value, '\\')) ) // A malicious remote machine could invalidate the above assert.
*breakpt = 0; if (breakpt == NULL)
{
break;
}
const char *valstart = breakpt + 1;
if ( (breakpt = strchr (valstart, '\\')) != NULL )
{
value = D_UnescapeUserInfo(valstart, breakpt - valstart);
}
else
{
value = D_UnescapeUserInfo(valstart, strlen(valstart));
}
int j = 0; for (j = 0;
while (UserInfoStrings[j] && stricmp (UserInfoStrings[j], ptr) != 0) UserInfoStrings[j] && strnicmp (UserInfoStrings[j], ptr, valstart - ptr - 1) != 0;
j++; ++j)
{ }
if (UserInfoStrings[j] == NULL) if (UserInfoStrings[j] == NULL)
{ {
infotype = -1; infotype = -1;
@ -611,10 +675,6 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
infotype = j; infotype = j;
} }
} }
else
{ // Shush, GCC.
value = NULL;
}
switch (infotype) switch (infotype)
{ {
@ -718,13 +778,8 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
break; break;
} }
if (!compact)
{
*(value - 1) = '\\';
}
if (breakpt) if (breakpt)
{ {
*breakpt = '\\';
ptr = breakpt + 1; ptr = breakpt + 1;
} }
else else

View file

@ -2078,7 +2078,7 @@ static void M_PlayerSetupDrawer ()
screen->DrawText (label, PSetupDef.x, PSetupDef.y + LINEHEIGHT+yo, "Team", screen->DrawText (label, PSetupDef.x, PSetupDef.y + LINEHEIGHT+yo, "Team",
DTA_Clean, true, TAG_DONE); DTA_Clean, true, TAG_DONE);
screen->DrawText (value, x, PSetupDef.y + LINEHEIGHT+yo, screen->DrawText (value, x, PSetupDef.y + LINEHEIGHT+yo,
players[consoleplayer].userinfo.team == TEAM_None ? "None" : (unsigned)players[consoleplayer].userinfo.team >= NUM_TEAMS ? "None" :
TeamNames[players[consoleplayer].userinfo.team], TeamNames[players[consoleplayer].userinfo.team],
DTA_Clean, true, TAG_DONE); DTA_Clean, true, TAG_DONE);
@ -2279,6 +2279,7 @@ static BYTE smoke[1024] =
7, 7, 0, 5, 1, 6, 7, 9,12, 9,12,21,22,25,24,22,23,25,24,18,24,22,17,13,10, 9,10, 9, 6,11, 6, 5, 7, 7, 0, 5, 1, 6, 7, 9,12, 9,12,21,22,25,24,22,23,25,24,18,24,22,17,13,10, 9,10, 9, 6,11, 6, 5,
}; };
// This is one plasma and two rotozoomers. I think it turned out quite awesome.
static void M_RenderPlayerBackdrop () static void M_RenderPlayerBackdrop ()
{ {
BYTE *from; BYTE *from;
@ -2521,9 +2522,19 @@ static void M_PlayerNameNotChanged ()
static void M_PlayerNameChanged (FSaveGameNode *dummy) static void M_PlayerNameChanged (FSaveGameNode *dummy)
{ {
char command[SAVESTRINGSIZE+8]; const char *p;
FString command("name \"");
sprintf (command, "name \"%s\"", savegamestring); // Escape any backslashes or quotation marks before sending the name to the console.
for (p = savegamestring; *p != '\0'; ++p)
{
if (*p == '"' || *p == '\\')
{
command << '\\';
}
command << *p;
}
command << '"';
C_DoCommand (command); C_DoCommand (command);
} }

View file

@ -4478,7 +4478,7 @@ newline:
normal_token: normal_token:
ScriptPtr = (YYCURSOR >= YYLIMIT) ? ScriptEndPtr : cursor; ScriptPtr = (YYCURSOR >= YYLIMIT) ? ScriptEndPtr : cursor;
sc_StringLen = MIN (ScriptPtr - tok, MAX_STRING_SIZE-1); sc_StringLen = (unsigned int)MIN<size_t> (ScriptPtr - tok, MAX_STRING_SIZE-1);
if (tokens && (sc_TokenType == TK_StringConst || sc_TokenType == TK_NameConst)) if (tokens && (sc_TokenType == TK_StringConst || sc_TokenType == TK_NameConst))
{ {
sc_StringLen -= 2; sc_StringLen -= 2;