一次栈溢出导致 Modbus 寄存器被篡改的排查实录


一、问题现象

某日测试发现,在执行操作A之后通过modbus poll查看操作A次数,本来是每次+1的,但是操作A执行后,modbus_data_calib.dark_calib 计数不再正常 +1,而是变为异常大的数值;同时该结构体其他成员也被篡改,初步判定为踩内存。 (modbus_data_calib地址0x20058C9A,全局结构体)

 

二、定位过程

1.对全局结构体 modbus_data_calib 设置写访问断点,监控其内存被修改的行为

按下ctrl+B,对该变量添加​断点

2.复现问题,发现断点停在xMBPortSerialGetByte(&ucByte)这个函数中,发现写入地址 0x20058CA0 恰好落在全局变量 modbus_data_calib 区域内。

这说明:栈溢出后,栈指针越界,直接踩穿到了 .bss 段全局变量。

3.查看工程map文件,看内存分布情况,从 MAP 文件可见:

全局变量 .bss 结束于 0x20058FFF

栈(STACK)起始于 0x20059200,大小仅 1024 字节(1KB)

栈向下生长,溢出后会直接覆盖下方 .bss 全局变量

栈从高地址向低地址生长,而.bss段在低地址,栈溢出时会直接踩到相邻的全局变量区

4.现在基本确定是栈溢出了,下面开始排查什么地方导致的栈溢出。该问题属于高概率问题,可以通过断点逐步调试,定位到具体哪个函数。在执行操作A后,在操作A函数开头打上断点,随后逐步调试,最后将函数锁定在WriteDark 函数中,函数内定义了局部数组 u16 temp_buf[1024],大小为 2KB,但系统栈仅 1KB,函数调用时栈瞬间溢出,覆盖相邻的 .bss 全局变量区。

三、问题解决

  1. 局部大数组改为 static 或全局变量(放入 .bss,不占栈)
  2. 适当增大栈空间(如从 1K → 2K/4K)
  3. 禁止在函数内定义 >512 字节的局部数组

四、思考

如何在前期预防住栈溢出的风险?欢迎大家留言。

我是王工,关注我,不定期分享嵌入式相关经验

posted @ 2026-05-02 21:35  王工聊驱动  阅读(0)  评论(0)    收藏  举报