Initial commit — leak-hunt project complete
Five bugs identified and patched in retail Asheron's Call client: - v3b: palette refcount over-increment (3-byte NOP at two sites) - v5: RenderSurface PurgeResource no-op stub (vtable slot 2 thunk) - v11: two dangling-pointer crash guards (NULL-check + reorder) - v14: CEnvCell::Destroy ClipPlaneList leak (18-byte JMP to cleanup thunk) - v22: unpacker stale-pointer SEH guard (whole-function __try/__except) All five ship in leakfix.dll (117 KB, SHA d282f23c…) which is loaded by acclient.exe at process start via PE import table patching by tools/install_leakfix.py. Controlled 15-client fleet soak: unpatched control died at 26h with palette exhaustion; all 14 patched clients survived past that point and reached ≥5-day uptime. Residual ~15 MB/h growth traced to d3d9.dll's internal slab allocator (260KB surface backing buffers retained after Release). See REPORT.md §10 for the full investigation; conclusion is that it's unfixable from outside d3d9. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
57b5e43d0e
199 changed files with 1648333 additions and 0 deletions
72
dll/leakfix/stable/src.iter3/thunks.cpp
Normal file
72
dll/leakfix/stable/src.iter3/thunks.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// thunks.cpp — runtime replacements called by AC into our DLL
|
||||
#include "thunks.h"
|
||||
#include "ac_addrs.h"
|
||||
|
||||
// ===== v5 — replacement PurgeResource for RenderSurface / RenderTexture =====
|
||||
//
|
||||
// Vtable slots use thiscall (ECX = this). MSVC __fastcall(arg1, arg2)
|
||||
// receives arg1 in ECX and arg2 in EDX. EDX is scratch from the caller
|
||||
// and isn't used, so we make it an unused parameter.
|
||||
//
|
||||
// Effect: instead of the no-op stub `mov al,1; ret`, we now actually
|
||||
// call Destroy() on the resource (frees its D3D handle + heap state)
|
||||
// then return 1 so PurgeOldResources marks it cleanly purged.
|
||||
|
||||
typedef void (__fastcall *destroy_fn_t)(void* self, void* edx_unused);
|
||||
|
||||
extern "C" int __fastcall purge_rendersurface_thunk(void* self, void* /*edx*/) {
|
||||
((destroy_fn_t)ac::V5_RS_DESTROY_VA)(self, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" int __fastcall purge_rendertexture_thunk(void* self, void* /*edx*/) {
|
||||
((destroy_fn_t)ac::V5_RT_DESTROY_VA)(self, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ===== v14 — CEnvCell::Destroy ClipPlaneList cleanup =====
|
||||
//
|
||||
// EoR's CEnvCell::Destroy contains an 18-byte cleanup block at
|
||||
// 0x0052E661 that only zeros cplane_num without freeing the underlying
|
||||
// ClipPlaneList object. We replace those 18 bytes with a 5-byte
|
||||
// JMP rel32 into the naked thunk below + 13 NOPs.
|
||||
//
|
||||
// Register context at entry (preserved from caller):
|
||||
// esi = `this` (CEnvCell)
|
||||
// ebx = 0 (cleared earlier in Destroy — relied on by the original
|
||||
// buggy `mov [eax], ebx`)
|
||||
// edi/ebp = live in surrounding loop
|
||||
//
|
||||
// On exit, we JMP to V14_RESUME_VA (the instruction immediately after
|
||||
// the 18-byte block).
|
||||
|
||||
extern "C" __declspec(naked) void v14_clipplane_cleanup_thunk() {
|
||||
__asm {
|
||||
pushad ; preserve everything
|
||||
mov edi, [esi + 0xDC] ; outer ClipPlaneList wrapper ptr
|
||||
test edi, edi
|
||||
jz done
|
||||
mov ecx, [edi] ; inner ClipPlaneList ptr
|
||||
test ecx, ecx
|
||||
jz free_outer
|
||||
// Free the inner ClipPlaneList properly
|
||||
push ecx
|
||||
mov eax, ac::V14_CLIPPLANELIST_DTOR
|
||||
call eax ; ClipPlaneList::~ClipPlaneList (thiscall)
|
||||
pop ecx
|
||||
push ecx
|
||||
mov eax, ac::V14_OPERATOR_DELETE
|
||||
call eax ; operator delete(inner)
|
||||
add esp, 4
|
||||
free_outer:
|
||||
push edi
|
||||
mov eax, ac::V14_OPERATOR_DELETE_ARR
|
||||
call eax ; operator delete[](outer)
|
||||
add esp, 4
|
||||
mov dword ptr [esi + 0xDC], 0 ; clear back-pointer
|
||||
done:
|
||||
popad
|
||||
push ac::V14_RESUME_VA ; jmp to resume point
|
||||
ret
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue