diff --git a/rehlds/HLTV/Proxy/build.gradle b/rehlds/HLTV/Proxy/build.gradle index 89778c5..dc191a0 100644 --- a/rehlds/HLTV/Proxy/build.gradle +++ b/rehlds/HLTV/Proxy/build.gradle @@ -16,6 +16,8 @@ project.ext.dep_bzip2 = project(':dep/bzip2') void setupToolchain(NativeBinarySpec b) { boolean useGcc = project.hasProperty("useGcc") + boolean rehltvFixes = b.flavor.name.contains('rehltvFixes') + def cfg = rootProject.createToolchainConfig(b); cfg.projectInclude(project, '/..', '/../..', '/src', '/../Director/src', '/../../common', '/../../engine', '/../../public', '/../../public/rehlds', '/../../pm_shared'); cfg.projectInclude(dep_bzip2, '/include') @@ -64,6 +66,10 @@ void setupToolchain(NativeBinarySpec b) { cfg.extraLibs "steam_api" } + if (rehltvFixes) { + cfg.singleDefines 'REHLTV_FIXES', 'REHLTV_CHECKS' + } + ToolchainConfigUtils.apply(project, cfg, b); } diff --git a/rehlds/HLTV/common/NetChannel.cpp b/rehlds/HLTV/common/NetChannel.cpp index ac1240a..34cc85d 100644 --- a/rehlds/HLTV/common/NetChannel.cpp +++ b/rehlds/HLTV/common/NetChannel.cpp @@ -653,6 +653,44 @@ bool NetChannel::CheckForCompletion(int stream, int intotalbuffers) return false; } +#ifdef REHLTV_FIXES +bool NetChannel::ValidateFragments(int pkt_size, qboolean *frag_message, unsigned int *fragid, int *frag_offset, int *frag_length) +{ + for (int i = 0; i < MAX_STREAMS; i++) + { + if (!frag_message[i]) + continue; + + // total fragments should be <= MAX_FRAGMENTS and current fragment can't be > total fragments + if (i == FRAG_NORMAL_STREAM && FRAG_GETCOUNT(fragid[i]) > MAX_NORMAL_FRAGMENTS) + return false; + if (i == FRAG_FILE_STREAM && FRAG_GETCOUNT(fragid[i]) > MAX_FILE_FRAGMENTS) + return false; + if (FRAG_GETID(fragid[i]) > FRAG_GETCOUNT(fragid[i])) + return false; + if (!frag_length[i]) + return false; + if ((size_t)frag_length[i] > FRAGMENT_MAX_SIZE || (size_t)frag_offset[i] > MAX_POSSIBLE_MSG - 1) + return false; + + int frag_end = frag_offset[i] + frag_length[i]; + + // end of fragment is out of the packet + if (frag_end + msg_readcount > pkt_size) + return false; + + // fragment overlaps next stream's fragment or placed after it + for (int j = i + 1; j < MAX_STREAMS; j++) + { + if (frag_end > frag_offset[j] && frag_message[j]) // don't add msg_readcount for comparison + return false; + } + } + + return true; +} +#endif // REHLTV_FIXES + void NetChannel::ProcessIncoming(unsigned char *data, int size) { BitBuffer message(data, size); @@ -721,6 +759,11 @@ void NetChannel::ProcessIncoming(unsigned char *data, int size) frag_length[i] = message.ReadShort(); } } + +#ifdef REHLTV_FIXES + if (!ValidateFragments(size, frag_message, fragid, frag_offset, frag_length)) + return; +#endif } sequence &= ~(1 << 31); diff --git a/rehlds/HLTV/common/NetChannel.h b/rehlds/HLTV/common/NetChannel.h index 8c396e3..18b00f9 100644 --- a/rehlds/HLTV/common/NetChannel.h +++ b/rehlds/HLTV/common/NetChannel.h @@ -53,6 +53,15 @@ enum #define MAX_LATENT 32 #define FRAGMENT_MAX_SIZE 1400 // Size of fragmentation buffer internal buffers +#define CLIENT_FRAGMENT_SIZE_ONCONNECT 128 +#define CUSTOMIZATION_MAX_SIZE 20480 + +// Client sends normal fragments only while connecting +#define MAX_NORMAL_FRAGMENTS (MAX_POSSIBLE_MSG / CLIENT_FRAGMENT_SIZE_ONCONNECT) + +// While client is connecting it sending fragments with minimal size, also it transfers sprays with minimal fragments... +// But with sv_delayed_spray_upload it sends with cl_dlmax fragment size +#define MAX_FILE_FRAGMENTS (CUSTOMIZATION_MAX_SIZE / FRAGMENT_C2S_MIN_SIZE) #define UDP_HEADER_SIZE 28 #define MAX_RELIABLE_PAYLOAD 1200 @@ -152,6 +161,9 @@ public: fragbuf_t *fragbufs; // The actual buffers } fragbufwaiting_t; +#ifdef REHLTV_FIXES + bool ValidateFragments(int pkt_size, qboolean *frag_message, unsigned int *fragid, int *frag_offset, int *frag_length); +#endif bool CreateFragmentsFromFile(char *fileName); bool CopyFileFragments(); void GetFlowStats(float *avgInKBSec, float *avgOutKBSec);