From 267c7eb327d48ffa5e37280506130f9713407f2e Mon Sep 17 00:00:00 2001 From: asmodai Date: Sat, 16 Jan 2016 23:52:17 +0300 Subject: [PATCH] Fixed crash in Q_UnicodeConvertT Refactoring in SV_ExtractFrom Added Steam_GSBUpdateUserData hook Refactored and optimized calculateBytecount without hardcode --- rehlds/engine/delta_jit.cpp | 73 ++++++++++-------------------- rehlds/engine/sv_main.cpp | 23 +++++----- rehlds/engine/sv_steam3.cpp | 15 ++++-- rehlds/engine/tmessage.cpp | 8 ++-- rehlds/engine/unicode_strtools.cpp | 12 ++--- rehlds/public/rehlds/rehlds_api.h | 10 +++- rehlds/rehlds/rehlds_api_impl.cpp | 8 +++- rehlds/rehlds/rehlds_api_impl.h | 10 +++- 8 files changed, 81 insertions(+), 78 deletions(-) diff --git a/rehlds/engine/delta_jit.cpp b/rehlds/engine/delta_jit.cpp index 8644fb4..69c48a5 100644 --- a/rehlds/engine/delta_jit.cpp +++ b/rehlds/engine/delta_jit.cpp @@ -321,7 +321,8 @@ void CDeltaCheckJIT::iterateStrings(deltajitdata_t *jitdesc) pushed_size += 8; } - add(esp, pushed_size); + if (pushed_size) + add(esp, pushed_size); } class CDeltaClearMarkFieldsJIT : public jitasm::function @@ -380,60 +381,36 @@ void CDeltaClearMarkFieldsJIT::calculateBytecount() { mov(eax, dword_ptr[ebx + delta_markbits_offset]); xor_(edx, edx); - // 0-7 + // bits 0-7 test(al, al); setnz(dl); - // 8-15 - if (jitdesc->numFields > 7) - { - mov(esi, 2); - test(ah, ah); - cmovnz(edx, esi); - } + for (size_t i = 1; i < DELTAJIT_MAX_FIELDS / 8; i++) { + const int byteid = i & 3; - // 16-23 - if (jitdesc->numFields > 15) - { - mov(ecx, 3); - test(eax, 0xFF0000); - cmovnz(edx, ecx); - } + if (byteid == 0) + mov(eax, dword_ptr[ebx + delta_markbits_offset + i]); - // 24-31 - if (jitdesc->numFields > 23) - { - mov(esi, 4); - test(eax, 0xFF000000); - cmovnz(edx, esi); - } + auto reg = (i & 1) ? ecx : esi; + auto prev = (i & 1) ? esi : ecx; - if (jitdesc->numFields > 31) - { - mov(eax, dword_ptr[ebx + delta_markbits_offset + 4]); + if (jitdesc->numFields > i * 8 - 1) { + mov(reg, i + 1); + if(i != 1) cmovnz(edx, prev); - // 32-39 - mov(ecx, 5); - test(al, al); - cmovnz(edx, ecx); - - // 40-47 - if (jitdesc->numFields > 39) - { - mov(esi, 6); - test(ah, ah); - cmovnz(edx, esi); + switch (byteid) { + case 0: test(al, al); break; + case 1: test(ah, ah); break; + default: test(eax, 0xFF << (byteid * 8)); + } } - - // 48-55 - if (jitdesc->numFields > 47) - { - mov(ecx, 7); - test(eax, 0xFF0000); - cmovnz(edx, ecx); + else if (jitdesc->numFields > unsigned(i * 8 - 9)) { + cmovnz(edx, prev); + break; } - - // maxfields is 56 + } + if (jitdesc->numFields > DELTAJIT_MAX_FIELDS - 9) { + cmovnz(edx, (DELTAJIT_MAX_FIELDS / 8 & 1) ? esi : ecx); } size_t delta_masksize_offset = offsetof(CDeltaJit, markedFieldsMaskSize); @@ -513,7 +490,7 @@ CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr d CUniqueLabel no_markedbits("no_markedbits"); CUniqueLabel calculated("calculated"); - test(edi, edi); + //test(edi, edi); // flags are already set jz(no_markedbits); calculateBytecount(); jmp(calculated); @@ -775,4 +752,4 @@ void CDeltaJitRegistry::Cleanup() { cur = cur->next; } #endif -} +} \ No newline at end of file diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index 3d394b2..e71929c 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -2411,7 +2411,11 @@ void EXT_FUNC SV_ConnectClient_internal(void) bIsSecure = Steam_GSBSecure(); Netchan_OutOfBandPrint(NS_SERVER, adr, "%c %i \"%s\" %i %i", 66, host_client->userid, NET_AdrToString(host_client->netchan.remote_address), bIsSecure, build_number()); Log_Printf("\"%s<%i><%s><>\" connected, address \"%s\"\n", name, host_client->userid, SV_GetClientIDString(host_client), NET_AdrToString(host_client->netchan.remote_address)); +#ifdef REHLDS_FIXES + Q_strncpy(host_client->userinfo, userinfo, MAX_INFO_STRING - 1); +#else Q_strncpy(host_client->userinfo, userinfo, MAX_INFO_STRING); +#endif host_client->userinfo[MAX_INFO_STRING - 1] = 0; SV_ExtractFromUserinfo(host_client); @@ -4799,15 +4803,13 @@ void SV_ExtractFromUserinfo(client_t *cl) const char *val; int i; char newname[MAX_NAME]; - char rawname[MAX_NAME]; - char *userinfo = cl->userinfo; val = Info_ValueForKey(userinfo, "name"); - Q_strncpy(rawname, val, sizeof(rawname) - 1); - rawname[sizeof(rawname) - 1] = 0; + Q_strncpy(newname, val, sizeof(newname) - 1); + newname[sizeof(newname) - 1] = '\0'; - for (char *p = rawname; *p; p++) + for (char *p = newname; *p; p++) { if (*p == '%' || *p == '&' @@ -4819,10 +4821,9 @@ void SV_ExtractFromUserinfo(client_t *cl) } #ifdef REHLDS_FIXES - Q_strcpy(newname, rawname); Q_StripUnprintableAndSpace(newname); #else // REHLDS_FIXES - TrimSpace(rawname, newname); + TrimSpace(newname, newname); #endif // REHLDS_FIXES if (!Q_UnicodeValidate(newname)) @@ -4831,9 +4832,9 @@ void SV_ExtractFromUserinfo(client_t *cl) } // Fix name to not start with '#', so it will not resemble userid - for (char *p = rawname; *p == '#'; p++) *p = ' '; + for (char *p = newname; *p == '#'; p++) *p = ' '; - if (newname[0] == 0 || !Q_stricmp(newname, "console") + if (newname[0] == '\0' || !Q_stricmp(newname, "console") #ifdef REHLDS_FIXES || Q_strstr(newname, "..") != NULL) #else // REHLDS_FIXES @@ -4854,7 +4855,7 @@ void SV_ExtractFromUserinfo(client_t *cl) val = Info_ValueForKey(userinfo, "name"); Q_strncpy(cl->name, val, sizeof(cl->name) - 1); - cl->name[sizeof(cl->name) - 1] = 0; + cl->name[sizeof(cl->name) - 1] = '\0'; ISteamGameServer_BUpdateUserData(cl->network_userid.m_SteamID, cl->name, 0); @@ -7329,4 +7330,4 @@ NOXREF qboolean BIsValveGame(void) return TRUE; } return FALSE; -} +} \ No newline at end of file diff --git a/rehlds/engine/sv_steam3.cpp b/rehlds/engine/sv_steam3.cpp index 4c69b08..7a0177c 100644 --- a/rehlds/engine/sv_steam3.cpp +++ b/rehlds/engine/sv_steam3.cpp @@ -467,7 +467,11 @@ void CSteam3Server::RunFrame() if (!cl->active) continue; - CRehldsPlatformHolder::get()->SteamGameServer()->BUpdateUserData(CSteamID(cl->network_userid.m_SteamID), cl->name, cl->edict->v.frags); +#ifdef REHLDS_FIXES + ISteamGameServer_BUpdateUserData(cl->network_userid.m_SteamID, cl->name, cl->edict->v.frags); +#else + CRehldsPlatformHolder::get()->SteamGameServer()->BUpdateUserData(cl->network_userid.m_SteamID, cl->name, cl->edict->v.frags); +#endif } if (CRehldsPlatformHolder::get()->SteamGameServer()->WasRestartRequested()) @@ -647,6 +651,11 @@ uint64 ISteamGameServer_CreateUnauthenticatedUserConnection(void) return CRehldsPlatformHolder::get()->SteamGameServer()->CreateUnauthenticatedUserConnection().ConvertToUint64(); } +bool Steam_GSBUpdateUserData(uint64 steamIDUser, const char *pchPlayerName, uint32 uScore) +{ + return CRehldsPlatformHolder::get()->SteamGameServer()->BUpdateUserData(steamIDUser, pchPlayerName, uScore); +} + /* ../engine/sv_steam3.cpp:559 */ bool ISteamGameServer_BUpdateUserData(uint64 steamid, const char *netname, uint32 score) { @@ -655,7 +664,7 @@ bool ISteamGameServer_BUpdateUserData(uint64 steamid, const char *netname, uint3 return false; } - return CRehldsPlatformHolder::get()->SteamGameServer()->BUpdateUserData(steamid, netname, score); + return g_RehldsHookchains.m_Steam_GSBUpdateUserData.callChain(Steam_GSBUpdateUserData, steamid, netname, score); } /* ../engine/sv_steam3.cpp:566 */ @@ -955,4 +964,4 @@ void Master_SetMaster_f(void) void Steam_HandleIncomingPacket(byte *data, int len, int fromip, uint16 port) { CRehldsPlatformHolder::get()->SteamGameServer()->HandleIncomingPacket(data, len, fromip, port); -} +} \ No newline at end of file diff --git a/rehlds/engine/tmessage.cpp b/rehlds/engine/tmessage.cpp index ab0835a..765a1dd 100644 --- a/rehlds/engine/tmessage.cpp +++ b/rehlds/engine/tmessage.cpp @@ -224,12 +224,12 @@ void TrimSpace(const char *source, char *dest) if (length <= 0) { - dest[0] = 0; + dest[0] = '\0'; } else { - Q_strncpy(dest, &source[start], length); - dest[length] = 0; + Q_memmove(dest, &source[start], length); + dest[length] = '\0'; } } @@ -507,4 +507,4 @@ NOXREF client_textmessage_t *TextMessageGet(const char *pName) return &gMessageTable[i]; } return NULL; -} +} \ No newline at end of file diff --git a/rehlds/engine/unicode_strtools.cpp b/rehlds/engine/unicode_strtools.cpp index c26aac1..82c928b 100644 --- a/rehlds/engine/unicode_strtools.cpp +++ b/rehlds/engine/unicode_strtools.cpp @@ -624,12 +624,13 @@ template< > int Q_UnicodeConvertT(const T_IN* pIn, T_OUT *pOut, int nOutBytes, enum EStringConvertErrorPolicy ePolicy) { + if (nOutBytes == 0) + return 0; + int nOut = 0; if (pOut) { - int nMaxOut = nOutBytes / sizeof(T_OUT) - 1; - if (nMaxOut <= 0) - return 0; + int nMaxOut = nOutBytes / sizeof(T_OUT) - 1; // print symbols count while (*pIn) { @@ -742,7 +743,7 @@ qboolean Q_StripUnprintableAndSpace(char *pch) int cch = Q_strlen(pch); int cubDest = (cch + 1) * sizeof(uchar16); - uchar16 *pwch_alloced = (uchar16*)malloc(cubDest); + uchar16 *pwch_alloced = (uchar16*)alloca(cubDest); bStrippedAny = false; bStrippedWhitespace = false; int cwch = (unsigned int)Q_UTF8ToUTF16(pch, (uchar16 *)pwch_alloced, cubDest, _STRINGCONVERTFLAG_ASSERT) >> 1; @@ -751,6 +752,5 @@ qboolean Q_StripUnprintableAndSpace(char *pch) if (bStrippedWhitespace || bStrippedAny) Q_UTF16ToUTF8(pwch, pch, cch, STRINGCONVERT_ASSERT_REPLACE); - free(pwch_alloced); return bStrippedAny; -} +} \ No newline at end of file diff --git a/rehlds/public/rehlds/rehlds_api.h b/rehlds/public/rehlds/rehlds_api.h index e7c38e3..2ab3fc5 100644 --- a/rehlds/public/rehlds/rehlds_api.h +++ b/rehlds/public/rehlds/rehlds_api.h @@ -35,7 +35,7 @@ #include "model.h" #define REHLDS_API_VERSION_MAJOR 2 -#define REHLDS_API_VERSION_MINOR 5 +#define REHLDS_API_VERSION_MINOR 6 //Steam_NotifyClientConnect hook typedef IHookChain IRehldsHook_Steam_NotifyClientConnect; @@ -165,6 +165,11 @@ typedef IHookChainRegistry IRehldsHookRegistry_Steam_GSGetSteamID; typedef IHookChain IRehldsHook_SV_TransferConsistencyInfo; typedef IHookChainRegistry IRehldsHookRegistry_SV_TransferConsistencyInfo; +//Steam_GSBUpdateUserData hook +typedef IHookChain IRehldsHook_Steam_GSBUpdateUserData; +typedef IHookChainRegistry IRehldsHookRegistry_Steam_GSBUpdateUserData; + +//BUpdateUserData class IRehldsHookchains { public: virtual ~IRehldsHookchains() { } @@ -201,6 +206,7 @@ public: virtual IRehldsHookRegistry_SV_WriteVoiceCodec* SV_WriteVoiceCodec() = 0; virtual IRehldsHookRegistry_Steam_GSGetSteamID* Steam_GSGetSteamID() = 0; virtual IRehldsHookRegistry_SV_TransferConsistencyInfo* SV_TransferConsistencyInfo() = 0; + virtual IRehldsHookRegistry_Steam_GSBUpdateUserData* Steam_GSBUpdateUserData() = 0; }; struct RehldsFuncs_t { @@ -261,4 +267,4 @@ public: virtual IRehldsFlightRecorder* GetFlightRecorder() = 0; }; -#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001" +#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001" \ No newline at end of file diff --git a/rehlds/rehlds/rehlds_api_impl.cpp b/rehlds/rehlds/rehlds_api_impl.cpp index 386c1d7..5c8fff3 100644 --- a/rehlds/rehlds/rehlds_api_impl.cpp +++ b/rehlds/rehlds/rehlds_api_impl.cpp @@ -346,7 +346,7 @@ IRehldsHookRegistry_SV_WriteVoiceCodec* CRehldsHookchains::SV_WriteVoiceCodec() return &m_SV_WriteVoiceCodec; } -CRehldsHookRegistry_Steam_GSGetSteamID* CRehldsHookchains::Steam_GSGetSteamID() { +IRehldsHookRegistry_Steam_GSGetSteamID* CRehldsHookchains::Steam_GSGetSteamID() { return &m_Steam_GSGetSteamID; } @@ -354,6 +354,10 @@ CRehldsHookRegistry_SV_TransferConsistencyInfo* CRehldsHookchains::SV_TransferCo return &m_SV_TransferConsistencyInfo; } +IRehldsHookRegistry_Steam_GSBUpdateUserData* CRehldsHookchains::Steam_GSBUpdateUserData() { + return &m_Steam_GSBUpdateUserData; +} + int EXT_FUNC CRehldsApi::GetMajorVersion() { return REHLDS_API_VERSION_MAJOR; @@ -386,4 +390,4 @@ IRehldsFlightRecorder* EXT_FUNC CRehldsApi::GetFlightRecorder() { return g_FlightRecorder; } -EXPOSE_SINGLE_INTERFACE(CRehldsApi, IRehldsApi, VREHLDS_HLDS_API_VERSION); +EXPOSE_SINGLE_INTERFACE(CRehldsApi, IRehldsApi, VREHLDS_HLDS_API_VERSION); \ No newline at end of file diff --git a/rehlds/rehlds/rehlds_api_impl.h b/rehlds/rehlds/rehlds_api_impl.h index beb10b0..432afe8 100644 --- a/rehlds/rehlds/rehlds_api_impl.h +++ b/rehlds/rehlds/rehlds_api_impl.h @@ -159,6 +159,10 @@ typedef IHookChainRegistryImpl CRehldsHookRegistry_Steam_GSGetSteamID; typedef IHookChainImpl CRehldsHook_SV_TransferConsistencyInfo; typedef IHookChainRegistryImpl CRehldsHookRegistry_SV_TransferConsistencyInfo; +//Steam_GSBUpdateUserData hook +typedef IHookChainImpl CRehldsHook_Steam_GSBUpdateUserData; +typedef IHookChainRegistryImpl CRehldsHookRegistry_Steam_GSBUpdateUserData; + class CRehldsHookchains : public IRehldsHookchains { public: CRehldsHookRegistry_Steam_NotifyClientConnect m_Steam_NotifyClientConnect; @@ -193,6 +197,7 @@ public: CRehldsHookRegistry_SV_WriteVoiceCodec m_SV_WriteVoiceCodec; CRehldsHookRegistry_Steam_GSGetSteamID m_Steam_GSGetSteamID; CRehldsHookRegistry_SV_TransferConsistencyInfo m_SV_TransferConsistencyInfo; + CRehldsHookRegistry_Steam_GSBUpdateUserData m_Steam_GSBUpdateUserData; public: virtual IRehldsHookRegistry_Steam_NotifyClientConnect* Steam_NotifyClientConnect(); @@ -225,7 +230,8 @@ public: virtual IRehldsHookRegistry_SV_DropClient* SV_DropClient(); virtual IRehldsHookRegistry_SV_ActivateServer* SV_ActivateServer(); virtual IRehldsHookRegistry_SV_WriteVoiceCodec* SV_WriteVoiceCodec(); - virtual CRehldsHookRegistry_Steam_GSGetSteamID* Steam_GSGetSteamID(); + virtual IRehldsHookRegistry_Steam_GSGetSteamID* Steam_GSGetSteamID(); + virtual IRehldsHookRegistry_Steam_GSBUpdateUserData* Steam_GSBUpdateUserData(); virtual CRehldsHookRegistry_SV_TransferConsistencyInfo* SV_TransferConsistencyInfo(); }; @@ -248,4 +254,4 @@ public: extern sizebuf_t* GetNetMessage_api(); extern IGameClient* GetHostClient_api(); -extern int* GetMsgReadCount_api(); +extern int* GetMsgReadCount_api(); \ No newline at end of file