mirror of
https://git.sanhost.net/sanasol/hytale-f2p
synced 2026-02-26 09:21:48 -03:00
Fix buffer overflow in Discord URL patch - likely cause of crashes
The Discord URL patch was writing 28 bytes (.gg/MHkEjepMQ7, 14 chars) where only 20 bytes existed (.gg/hytale, 10 chars), corrupting 8 bytes of adjacent data in the binary. Changes: - Use same-length Discord URL: .gg/santop (10 chars) - Add length check to UTF-16LE fallback path - Add length check and zero-fill to findAndReplaceDomainSmart This buffer overflow explains why the crash happened on some systems (Steam Deck, Ubuntu LTS) but not others - depending on what data was adjacent to the patched string. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -203,11 +203,19 @@ class ClientPatcher {
|
||||
* .NET AOT stores some strings in various formats:
|
||||
* - Standard UTF-16LE (each char is 2 bytes with \x00 high byte)
|
||||
* - Length-prefixed where last char may have metadata byte instead of \x00
|
||||
*
|
||||
* IMPORTANT: newDomain must be same length or shorter than oldDomain to avoid buffer overflow
|
||||
*/
|
||||
findAndReplaceDomainSmart(data, oldDomain, newDomain) {
|
||||
let count = 0;
|
||||
const result = Buffer.from(data);
|
||||
|
||||
// Safety check: new domain must not be longer than old
|
||||
if (newDomain.length > oldDomain.length) {
|
||||
console.warn(` Warning: New domain (${newDomain.length} chars) longer than old (${oldDomain.length} chars), skipping smart replacement`);
|
||||
return { buffer: result, count: 0 };
|
||||
}
|
||||
|
||||
const oldUtf16NoLast = this.stringToUtf16LE(oldDomain.slice(0, -1));
|
||||
const newUtf16NoLast = this.stringToUtf16LE(newDomain.slice(0, -1));
|
||||
|
||||
@@ -223,6 +231,11 @@ class ClientPatcher {
|
||||
const lastCharFirstByte = result[lastCharPos];
|
||||
|
||||
if (lastCharFirstByte === oldLastCharByte) {
|
||||
// Zero-fill the old region first if new is shorter
|
||||
if (newUtf16NoLast.length < oldUtf16NoLast.length) {
|
||||
result.fill(0x00, pos, pos + oldUtf16NoLast.length);
|
||||
}
|
||||
|
||||
newUtf16NoLast.copy(result, pos);
|
||||
|
||||
result[lastCharPos] = newLastCharByte;
|
||||
@@ -316,14 +329,21 @@ class ClientPatcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch Discord invite URLs from .gg/hytale to .gg/MHkEjepMQ7
|
||||
* Patch Discord invite URLs from .gg/hytale to shorter URL
|
||||
* IMPORTANT: New URL must be same length or shorter to avoid corrupting adjacent data
|
||||
*/
|
||||
patchDiscordUrl(data) {
|
||||
let count = 0;
|
||||
const result = Buffer.from(data);
|
||||
|
||||
const oldUrl = '.gg/hytale';
|
||||
const newUrl = '.gg/MHkEjepMQ7';
|
||||
// Use same-length URL to avoid buffer overflow
|
||||
// Original: .gg/hytale (10 chars)
|
||||
// New: .gg/gME8rUy3MB would be 14 chars - TOO LONG
|
||||
// Using: .gg/sanasolf2p (13 chars) - still too long
|
||||
// Using: .gg/hytalef2p (12 chars) - still too long
|
||||
// Must be exactly 10 chars: .gg/XXXXXX (6 chars after .gg/)
|
||||
const newUrl = '.gg/santop'; // 10 chars - same length, points to our server list
|
||||
|
||||
// Try length-prefixed format first
|
||||
const lpResult = this.replaceBytes(
|
||||
@@ -336,13 +356,22 @@ class ClientPatcher {
|
||||
return { buffer: lpResult.buffer, count: lpResult.count };
|
||||
}
|
||||
|
||||
// Fallback to UTF-16LE
|
||||
// Fallback to UTF-16LE - but ONLY if same length to avoid corruption
|
||||
const oldUtf16 = this.stringToUtf16LE(oldUrl);
|
||||
const newUtf16 = this.stringToUtf16LE(newUrl);
|
||||
|
||||
if (newUtf16.length > oldUtf16.length) {
|
||||
console.warn(` Warning: Discord URL replacement skipped - new URL longer than old`);
|
||||
return { buffer: result, count: 0 };
|
||||
}
|
||||
|
||||
const positions = this.findAllOccurrences(result, oldUtf16);
|
||||
|
||||
for (const pos of positions) {
|
||||
// Zero-fill first if new is shorter
|
||||
if (newUtf16.length < oldUtf16.length) {
|
||||
result.fill(0x00, pos, pos + oldUtf16.length);
|
||||
}
|
||||
newUtf16.copy(result, pos);
|
||||
count++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user