异常dump分析

背景

游戏遇到一个crash问题,希望我能帮忙看看。

分析过程

本身游戏是接入了我之前提供的crash lib 所以一旦异常立刻会保存dump并记录异常上下文。拿到dump,加载pdb文件,通过

1
2
3
4
5
6
7
8
9
!analyze -v 

FAILURE_BUCKET_ID: STACK_BUFFER_OVERRUN_STACK_BUFFER_OVERRUN_MISSING_GSFRAME_c0000409_roomsvrzgxr.exe!CRoomData::SendRandomPlaying

并通过 .ecxr 找到异常触发函数

roomsvrzgxr!CRoomData::SendRandomPlaying+0x129 [d:\roomsvrzgxr\roomdata.cpp@[281]
roomsvrzgxr!CRoomData::LaunchGame+0x9b [d:\roomsvrzgxr\roomdata.cpp @ [439]
roomsvrzgxr!CRoomData::LaunchGame+0x2f [d:\roomsvrzgxr\roomdata.cpp @ 452]

可以确定原因是由于 栈溢出导致的。 因为程序默认开始了/GS (Buffer Security Check)功能,所以在检测到栈溢出时会直接抛出异常,这个异常的捕获需要特殊处理才能捕获,可以参考我之前的文章。

以我的经验这类问题一般都是字符串格式化参数错误导致,所以搜索了下代码没有相关性。

或者是局部变量内存复制越界,所以看了下指定函数代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
WAIT_TIME_FOR_ARRANGE_TABLE stuCostTimeOfArrangingTable;
ZeroMemory(&stuCostTimeOfArrangingTable, sizeof(stuCostTimeOfArrangingTable));
stuCostTimeOfArrangingTable.nGameID = GAME_ID;
stuCostTimeOfArrangingTable.nRoomType = GetRoomType();

LPLTPLAYER pLTPlayer = NULL;
LTPLAYER stuLTPlayer;
for (int i = 0; i < pNewTable->th.nPlayerCount; i++)
{
stuCostTimeOfArrangingTable.stuItem[i].nUserID = pNewTable->nPlayerAry[i];

LPPLAYER lpPlayer = NULL;
if (m_mapPlayer.Lookup(pNewTable->nPlayerAry[i], lpPlayer))
{
auto tNow = time(NULL);
stuCostTimeOfArrangingTable.stuItem[i].nWaitTime = tNow - lpPlayer->pe.nEnterTime;
}
}

其中

1
2
3
4
5
6
7
8
9
10
typedef struct _tagWaitTimeForArrangeTable
{
int nGameID;
int nRoomType;
struct {
int nUserID;
//int nLTScore;
int nWaitTime;
} stuItem[TOTAL_CHAIRS];//TOTAL_CHAIRS=2
}WAIT_TIME_FOR_ARRANGE_TABLE, *LPWAIT_TIME_FOR_ARRANGE_TABLE;

stuCostTimeOfArrangingTable.stuItem[] 的最大索引是2. 那么是否可能存在pNewTable->th.nPlayerCount过大而导致溢出呢?

带着这个疑问去查找pNewTable的内容,nPlayerCount=3 ,那么刚好存在越界的可能。

upload successful