由memcpy越界引起的崩溃

前言

一个linux的cm出了问题,在开发环境下,是正常的。在现场是崩溃的。
比较环境的区别,输入的数据不一样。
还好运气不错,拿到现场的数据,在开发环境中也能重现其中一个数据引起的崩溃问题。

崩溃现象,单步到函数fnA, 任务都做了,看任务结果也都有效,但是从函数返回时,还没到调用处,就崩溃了。

这bug现象,我第一感觉就是发生了数据写的越界,导致栈上的返回地址被覆盖成了意料之外的地址。

因为其中一条数据可以重现bug, 就去单步,开始没看出来。再单步时,看看有啥写数据的操作,用 p 或 x/16ab 打印长度和变量缓冲区,发现这个cm是以前写的,在内存拷贝时,用到了memcpy,但是没有做参数检查,当源数据长度超过目标缓冲区长度时,将低地址的变量超长度写入数据,根据栈上局部变量的数量和size, 当超长度越界写入达到一定长度时,就将栈上高地址的函数返回地址写到了,返回地址乱了。当返回时,到了未知区域,如果执行的汇编代码不对了(看运气),执行了不可访问的额操作,引起c05错误,程序就 崩溃了。
查了一下cm中调用memcpy的地方,还很多,就封装了一个函数safe_copy_buf,供各处调用。重构完成时,必现的崩溃没有了,偶发的崩溃问题也没有了。

看来,要使程序健壮,每个细节都要注意 😃

实验

当代码片段使用超过2次,都值得封装一个函数,供其他函数调用。
这样做,维护性,可调试性,代码清晰度, 都提高了。
当工程代码量上来时,如果出了这种越界写的问题,又不能必现(偶发),还是蛮头疼的。

void safe_copy_buf(unsigned char* puc_dst, int i_len_dst, unsigned char* puc_src, int i_len_src)
{
	int i_len_to_copy = 0;
	
	do {
		if ((NULL == puc_dst) || (NULL == puc_src)) {
			break;
		}

		i_len_to_copy = (i_len_src < i_len_dst) ? i_len_src : i_len_dst;
		memset(puc_dst, 0, i_len_dst);

		if (i_len_to_copy <= 0) {
			break;
		}

		memcpy(puc_dst, puc_src, i_len_to_copy);
	} while (0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值