From d1aa7a2c0206c0e98e08019443f408f3c74a3603 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Thu, 28 May 2026 14:53:12 +0200 Subject: [PATCH] Fix: guard IOCPClient against early packet before setManagerCallBack --- client/IOCPClient.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/client/IOCPClient.cpp b/client/IOCPClient.cpp index 60468fa..59952d4 100644 --- a/client/IOCPClient.cpp +++ b/client/IOCPClient.cpp @@ -218,6 +218,13 @@ IOCPClient::IOCPClient(const State&bExit, bool exit_while_disconnect, int mask, m_ServerAddr = {}; m_nHostPort = 0; m_Manager = NULL; + // 防御性初始化:避免 Debug build 里 0xcdcdcdcd 堆 fill 让 Receive 线程 + // 在调用方 setManagerCallBack() 之前就读到野指针。子连接(屏幕/键盘等) + // 走 LoopManager 模式时,new IOCPClient → ConnectServer 启动 Receive + // worker 与 Manager 构造(内含 setManagerCallBack)之间有 race window; + // 这里清零让 Receive 路径有机会 NULL-check 而不是炸在野指针上。 + m_DataProcess = NULL; + m_ReconnectFunc = NULL; m_masker = mask ? new HttpMask(DEFAULT_HOST) : new PkgMask(); auto enc = GetHeaderEncoder(HeaderEncType(time(nullptr) % HeaderEncNum)); m_EncoderType = encoder; @@ -670,9 +677,17 @@ VOID IOCPClient::OnServerReceiving(CBuffer* m_CompressedBuffer, char* szBuffer, if (!TryHandleAuthResponse(DeCompressedBuffer, ulOriginalLength)) { //解压好的数据和长度传递给对象Manager进行处理 注意这里是用了多态 //由于m_pManager中的子类不一样造成调用的OnReceive函数不一样 - int ret = DataProcessWithSEH(m_DataProcess, m_Manager, DeCompressedBuffer, ulOriginalLength); - if (ret) { - Mprintf("[ERROR] DataProcessWithSEH return exception code: [0x%08X]\n", ret); + // 防御 race window:子连接 ConnectServer 触发 Receive 后, + // 调用方 setManagerCallBack() 可能还没执行;丢弃这种早期包 + // 比让函数指针炸进 0xcdcdcd 强(pre-existing race,详见 + // 构造函数注释,长期需要在 ConnectServer 前 set callback) + if (m_DataProcess == NULL) { + Mprintf("[WARN] dropping early packet: setManagerCallBack not yet called\n"); + } else { + int ret = DataProcessWithSEH(m_DataProcess, m_Manager, DeCompressedBuffer, ulOriginalLength); + if (ret) { + Mprintf("[ERROR] DataProcessWithSEH return exception code: [0x%08X]\n", ret); + } } } } else {