diff --git a/game/reconstructed/btl4gau2.cpp b/game/reconstructed/btl4gau2.cpp index ace13f7..e270be9 100644 --- a/game/reconstructed/btl4gau2.cpp +++ b/game/reconstructed/btl4gau2.cpp @@ -127,6 +127,33 @@ static void *AttributePointerOf(void *subsystem, const char *name) return p; } +// +// BT412 DATABINDING GUARD [T3]: is `p` a readable committed address? The +// plug->link->subsystem chain below walks raw +8 offsets recovered from the +// 1995 binary, but our reconstructed subsystem layout is NOT byte-identical, +// so an intermediate "link" can come out non-null-but-garbage -- dereferencing +// it AVs (observed: CoolingLoopConnection::Update crash the moment a mech's +// coolant loop goes active, on the pod AND the dev composite). A readable-page +// check makes an invalid link resolve to the authentic "no source" branch (0) +// instead of faulting. Proper fix (follow-up): route through named Plug/Link +// accessors in a complete-type TU instead of raw +8 reads. +// +static bool BTPtrReadable(const void *p) +{ + if (p == 0) + return false; + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery(p, &mbi, sizeof(mbi)) == 0) + return false; + if (mbi.State != MEM_COMMIT) + return false; + const DWORD readable = PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ + | PAGE_EXECUTE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY; + if ((mbi.Protect & readable) == 0) + return false; + return (mbi.Protect & PAGE_GUARD) == 0; +} + // // FUN_00417ab4 -- SubsystemConnection::Resolve: follow the plug's bound link to the // resolved subsystem. The link is `*(plug+8)`; the resolved subsystem is @@ -136,10 +163,10 @@ static void *AttributePointerOf(void *subsystem, const char *name) // static void *ResolveLink(void *plug) { - if (plug == 0) + if (!BTPtrReadable((char *)plug + 8)) return 0; void *link = *(void **)((char *)plug + 8); - if (link == 0) + if (!BTPtrReadable((char *)link + 8)) // [T3] guard: layout-mismatch garbage link return 0; return *(void **)((char *)link + 8); } @@ -204,13 +231,17 @@ public: void Update() // @004c31a0 { void *resolved = 0; - if (source != 0 && *(int *)((char *)source + 0x134) == 1) + // [T3] guard the raw +0x134 / +0x1d4 reads against the layout mismatch + // (see BTPtrReadable above) -- an invalid chain reads "no source" (0). + if (BTPtrReadable((char *)source + 0x134) && + *(int *)((char *)source + 0x134) == 1) { void *linked = FindLinkedSubsystem(source, 3); if (linked != 0) resolved = ResolveLink(linked); } - *destination = (resolved == 0) ? 0 : *(int *)((char *)resolved + 0x1d4); + *destination = (resolved != 0 && BTPtrReadable((char *)resolved + 0x1d4)) + ? *(int *)((char *)resolved + 0x1d4) : 0; } protected: void *source; // @0x10 this[4]