Fix: guard IOCPClient against early packet before setManagerCallBack
This commit is contained in:
@@ -218,6 +218,13 @@ IOCPClient::IOCPClient(const State&bExit, bool exit_while_disconnect, int mask,
|
|||||||
m_ServerAddr = {};
|
m_ServerAddr = {};
|
||||||
m_nHostPort = 0;
|
m_nHostPort = 0;
|
||||||
m_Manager = NULL;
|
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();
|
m_masker = mask ? new HttpMask(DEFAULT_HOST) : new PkgMask();
|
||||||
auto enc = GetHeaderEncoder(HeaderEncType(time(nullptr) % HeaderEncNum));
|
auto enc = GetHeaderEncoder(HeaderEncType(time(nullptr) % HeaderEncNum));
|
||||||
m_EncoderType = encoder;
|
m_EncoderType = encoder;
|
||||||
@@ -670,11 +677,19 @@ VOID IOCPClient::OnServerReceiving(CBuffer* m_CompressedBuffer, char* szBuffer,
|
|||||||
if (!TryHandleAuthResponse(DeCompressedBuffer, ulOriginalLength)) {
|
if (!TryHandleAuthResponse(DeCompressedBuffer, ulOriginalLength)) {
|
||||||
//解压好的数据和长度传递给对象Manager进行处理 注意这里是用了多态
|
//解压好的数据和长度传递给对象Manager进行处理 注意这里是用了多态
|
||||||
//由于m_pManager中的子类不一样造成调用的OnReceive函数不一样
|
//由于m_pManager中的子类不一样造成调用的OnReceive函数不一样
|
||||||
|
// 防御 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);
|
int ret = DataProcessWithSEH(m_DataProcess, m_Manager, DeCompressedBuffer, ulOriginalLength);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
Mprintf("[ERROR] DataProcessWithSEH return exception code: [0x%08X]\n", ret);
|
Mprintf("[ERROR] DataProcessWithSEH return exception code: [0x%08X]\n", ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Mprintf("[ERROR] uncompress fail: dstLen %lu, srcLen %lu\n", ulOriginalLength, ulCompressedLength);
|
Mprintf("[ERROR] uncompress fail: dstLen %lu, srcLen %lu\n", ulOriginalLength, ulCompressedLength);
|
||||||
// ReadBuffer 已消费当前包,不需要清空缓冲区
|
// ReadBuffer 已消费当前包,不需要清空缓冲区
|
||||||
|
|||||||
Reference in New Issue
Block a user