mirror of
https://github.com/rehlds/rehlds.git
synced 2025-04-25 07:43:40 +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)
|
qboolean Info_IsValid(const char *s)
|
||||||
{
|
{
|
||||||
char key[MAX_KV_LEN];
|
|
||||||
char value[MAX_KV_LEN];
|
|
||||||
char *c;
|
|
||||||
int nCount;
|
|
||||||
|
|
||||||
while (*s)
|
while (*s)
|
||||||
{
|
{
|
||||||
if (*s == '\\')
|
if (*s == '\\')
|
||||||
@ -553,46 +548,48 @@ qboolean Info_IsValid(const char *s)
|
|||||||
s++; // skip the slash
|
s++; // skip the slash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy a key
|
// Returns character count
|
||||||
nCount = 0;
|
// -1 - error
|
||||||
c = key;
|
// 0 - string size is zero
|
||||||
while (*s != '\\')
|
enum class AllowNull {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
};
|
||||||
|
auto validate = [&s](AllowNull allowNull) -> int
|
||||||
|
{
|
||||||
|
int nCount = 0;
|
||||||
|
|
||||||
|
for(; *s != '\\'; nCount++, s++)
|
||||||
{
|
{
|
||||||
if (!*s)
|
if (!*s)
|
||||||
{
|
{
|
||||||
return FALSE; // key should end with a \, not a NULL
|
return (allowNull == AllowNull::Yes) ? nCount : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nCount >= MAX_KV_LEN)
|
if (nCount >= MAX_KV_LEN)
|
||||||
{
|
{
|
||||||
return FALSE; // key length should be less then MAX_KV_LEN
|
return -1; // string length should be less then MAX_KV_LEN
|
||||||
}
|
}
|
||||||
*c++ = *s++;
|
|
||||||
nCount++;
|
|
||||||
}
|
|
||||||
*c = 0;
|
|
||||||
s++; // skip the slash
|
|
||||||
|
|
||||||
// Copy a value
|
#ifdef REHLDS_FIXES
|
||||||
nCount = 0;
|
if (*s == '\"')
|
||||||
c = value;
|
|
||||||
while (*s != '\\')
|
|
||||||
{
|
{
|
||||||
if (!*s)
|
return -1; // string should not contain "
|
||||||
{
|
|
||||||
break; // allow value to be ended with NULL
|
|
||||||
}
|
}
|
||||||
if (nCount >= MAX_KV_LEN)
|
#endif
|
||||||
{
|
|
||||||
return FALSE; // value length should be less then MAX_KV_LEN
|
|
||||||
}
|
}
|
||||||
*c++ = *s++;
|
return nCount;
|
||||||
nCount++;
|
};
|
||||||
}
|
|
||||||
*c = 0;
|
|
||||||
|
|
||||||
if (value[0] == 0)
|
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)
|
if (!*s)
|
||||||
|
@ -1977,29 +1977,29 @@ int SV_CheckForDuplicateSteamID(client_t *client)
|
|||||||
|
|
||||||
int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot)
|
int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot)
|
||||||
{
|
{
|
||||||
const char *val;
|
|
||||||
int i;
|
|
||||||
client_t *client;
|
|
||||||
int dupc = 0;
|
int dupc = 0;
|
||||||
char rawname[MAX_NAME];
|
|
||||||
char newname[MAX_NAME];
|
|
||||||
int changed = FALSE;
|
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);
|
Q_strncpy(rawname, val, MAX_NAME - 1);
|
||||||
|
|
||||||
while (true)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no duplicates for current name
|
// no duplicates for current name
|
||||||
if (i == g_psvs.maxclients)
|
if (clientId == g_psvs.maxclients)
|
||||||
return changed;
|
return changed;
|
||||||
|
|
||||||
|
char newname[MAX_NAME];
|
||||||
Q_snprintf(newname, sizeof(newname), "(%d)%-0.*s", ++dupc, 28, rawname);
|
Q_snprintf(newname, sizeof(newname), "(%d)%-0.*s", ++dupc, 28, rawname);
|
||||||
#ifdef REHLDS_FIXES
|
#ifdef REHLDS_FIXES
|
||||||
// Fix possibly incorrectly cut UTF8 chars
|
// Fix possibly incorrectly cut UTF8 chars
|
||||||
|
Loading…
x
Reference in New Issue
Block a user