mirror of
https://github.com/rehlds/rehlds.git
synced 2025-01-14 15:48:04 +03:00
Fixes for new exploit involving " in info strings. (#596)
* Refactor SV_CheckForDuplicateNames * Refactor and fix Info_IsValid
This commit is contained in:
parent
19e3a5df56
commit
ce163a323b
@ -541,11 +541,6 @@ void Info_Print(const char *s)
|
||||
|
||||
qboolean Info_IsValid(const char *s)
|
||||
{
|
||||
char key[MAX_KV_LEN];
|
||||
char value[MAX_KV_LEN];
|
||||
char *c;
|
||||
int nCount;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == '\\')
|
||||
@ -553,46 +548,48 @@ qboolean Info_IsValid(const char *s)
|
||||
s++; // skip the slash
|
||||
}
|
||||
|
||||
// Copy a key
|
||||
nCount = 0;
|
||||
c = key;
|
||||
while (*s != '\\')
|
||||
// Returns character count
|
||||
// -1 - error
|
||||
// 0 - string size is zero
|
||||
enum class AllowNull {
|
||||
Yes,
|
||||
No,
|
||||
};
|
||||
auto validate = [&s](AllowNull allowNull) -> int
|
||||
{
|
||||
if (!*s)
|
||||
{
|
||||
return FALSE; // key should end with a \, not a NULL
|
||||
}
|
||||
if (nCount >= MAX_KV_LEN)
|
||||
{
|
||||
return FALSE; // key length should be less then MAX_KV_LEN
|
||||
}
|
||||
*c++ = *s++;
|
||||
nCount++;
|
||||
}
|
||||
*c = 0;
|
||||
s++; // skip the slash
|
||||
int nCount = 0;
|
||||
|
||||
// Copy a value
|
||||
nCount = 0;
|
||||
c = value;
|
||||
while (*s != '\\')
|
||||
{
|
||||
if (!*s)
|
||||
for(; *s != '\\'; nCount++, s++)
|
||||
{
|
||||
break; // allow value to be ended with NULL
|
||||
}
|
||||
if (nCount >= MAX_KV_LEN)
|
||||
{
|
||||
return FALSE; // value length should be less then MAX_KV_LEN
|
||||
}
|
||||
*c++ = *s++;
|
||||
nCount++;
|
||||
}
|
||||
*c = 0;
|
||||
if (!*s)
|
||||
{
|
||||
return (allowNull == AllowNull::Yes) ? nCount : -1;
|
||||
}
|
||||
|
||||
if (value[0] == 0)
|
||||
if (nCount >= MAX_KV_LEN)
|
||||
{
|
||||
return -1; // string length should be less then MAX_KV_LEN
|
||||
}
|
||||
|
||||
#ifdef REHLDS_FIXES
|
||||
if (*s == '\"')
|
||||
{
|
||||
return -1; // string should not contain "
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return nCount;
|
||||
};
|
||||
|
||||
if (validate(AllowNull::No) == -1)
|
||||
{
|
||||
return FALSE; // empty values are not valid
|
||||
return FALSE;
|
||||
}
|
||||
s++; // Skip slash
|
||||
|
||||
if (validate(AllowNull::Yes) <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
|
@ -1977,29 +1977,29 @@ int SV_CheckForDuplicateSteamID(client_t *client)
|
||||
|
||||
int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot)
|
||||
{
|
||||
const char *val;
|
||||
int i;
|
||||
client_t *client;
|
||||
int dupc = 0;
|
||||
char rawname[MAX_NAME];
|
||||
char newname[MAX_NAME];
|
||||
int changed = FALSE;
|
||||
|
||||
val = Info_ValueForKey(userinfo, "name");
|
||||
const char *val = Info_ValueForKey(userinfo, "name");
|
||||
|
||||
char rawname[MAX_NAME];
|
||||
Q_strncpy(rawname, val, MAX_NAME - 1);
|
||||
|
||||
while (true)
|
||||
{
|
||||
for (i = 0, client = g_psvs.clients; i < g_psvs.maxclients; i++, client++)
|
||||
int clientId = 0;
|
||||
client_t *client = &g_psvs.clients[0];
|
||||
for (; clientId < g_psvs.maxclients; clientId++, client++)
|
||||
{
|
||||
if (client->connected && !(i == nExcludeSlot && bIsReconnecting) && !Q_stricmp(client->name, val))
|
||||
if (client->connected && !(clientId == nExcludeSlot && bIsReconnecting) && !Q_stricmp(client->name, val))
|
||||
break;
|
||||
}
|
||||
|
||||
// no duplicates for current name
|
||||
if (i == g_psvs.maxclients)
|
||||
if (clientId == g_psvs.maxclients)
|
||||
return changed;
|
||||
|
||||
char newname[MAX_NAME];
|
||||
Q_snprintf(newname, sizeof(newname), "(%d)%-0.*s", ++dupc, 28, rawname);
|
||||
#ifdef REHLDS_FIXES
|
||||
// Fix possibly incorrectly cut UTF8 chars
|
||||
|
Loading…
x
Reference in New Issue
Block a user