问题描述
在开发新版本的答题器的时候,总是容易应发内存越界的问题,越界之后设备显示的数据都是错乱的,且不不停有调试信息打印输出
问题的分析
测试的是否发现只有新的设备会引发问题,于是定位问题在新的设备引发的问题,且突变的是时候调试信息的控制字突变,于是在DBG模式下测试,偶然发现这个控制字段整体突变为答题器打印信息的内容:
答题器答应信息的接口如下:
/*******************************************************************************
* Function Name : spi_rcmd_dtq_data
* Description : 答题器 data 处理
* Input : port : SPI 端口号
* Output : None
* Return : None
*******************************************************************************/
int8_t spi_rcmd_dtq_data(uint8_t port, rf_spi_pac_t *rf_pac)
{
int8_t ret = 1;
uint8_t rf_cmd = rf_pac->Data[1];
uint8_t upos = 0xff;
/* 白名单过滤 */
if (app_port_dtq_check(port, rf_pac->Data + 7, &upos) == 0)
{
if (upos <sys_tcb_val.port_max)
{
switch (rf_cmd)
{
case RF_CMD_ANSWER_UP: ret = spi_rcmd_dtq_answer_data(port, upos, rf_pac); break;
case RF_CMD_POWER_OFF:
case RF_CMD_POWER_ON: ret = spi_rcmd_dtq_power_data(port, upos, rf_pac); break;
case RF_CMD_DEBUG:
log_print("r_DTQ", port, "[ %10u ] uID[%2d:%10u]: %s",
*(uint32_t *)(rf_pac->Data + 3), upos,
*(uint32_t *)(rf_pac->Data + 7), rf_pac->Data+11);
break;
default: ret = 0; break;
}
}
}
else
{
if(rf_cmd == RF_CMD_DEBUG)
log_print("r_DTQ", port, "[ %10u ] uID[xx:%10u]: %s",
*(uint32_t *)(rf_pac->Data + 3),
*(uint32_t *)(rf_pac->Data + 7), rf_pac->Data+11);
}
return ret;
}
此处是直接接收答题器封装的调试信息用来输出,此处猜测是答题器发上来的数据 在 %s 这个指令解析时,没有查找到停止边界“\0”,导致的内存访问越界,注释掉此段调试信息之后发现问题消失了:
于是在操作这个数据包的时候强制给答题器发送上来的每个调试信息的数据包增加结尾符:
/*******************************************************************************
* Function Name : spi_rcmd_dtq_data
* Description : 答题器 ACK 处理
* Input : port : SPI 端口号
* Output : None
* Return : None
*******************************************************************************/
int8_t spi_rcmd_dtq_data(uint8_t port, rf_spi_pac_t *rf_pac)
{
int8_t ret = 1;
uint8_t rf_cmd = rf_pac->Data[1];
uint8_t upos = 0xff;
/* 白名单过滤 */
if (app_port_dtq_check(port, rf_pac->Data + 7, &upos) == 0)
{
if (upos <sys_tcb_val.port_max)
{
switch (rf_cmd)
{
case RF_CMD_ANSWER_UP: ret = spi_rcmd_dtq_answer_data(port, upos, rf_pac); break;
case RF_CMD_POWER_OFF:
case RF_CMD_POWER_ON: ret = spi_rcmd_dtq_power_data(port, upos, rf_pac); break;
case RF_CMD_DEBUG:
if(rf_pac->Len <= 242)
{
rf_pac->Data[rf_pac->Len] = 0;
log_print("r_DTQ", port, "[ %10u ] uID[%2d:%10u]: %s",
*(uint32_t *)(rf_pac->Data + 3), upos,
*(uint32_t *)(rf_pac->Data + 7), rf_pac->Data+11);
}
break;
default: ret = 0; break;
}
}
}
else
{
if(rf_cmd == RF_CMD_DEBUG)
{
if(rf_pac->Len <= 242)
{
rf_pac->Data[rf_pac->Len] = 0;
log_print("r_DTQ", port, "[ %10u ] uID[xx:%10u]: %s",
*(uint32_t *)(rf_pac->Data + 3),
*(uint32_t *)(rf_pac->Data + 7), rf_pac->Data+11);
}
}
}
return ret;
}
再次测试,还是有问题,接续查看日志输出底层函数定位问题是,原先定义的日志打印缓存的空间越界:
--- a/app/app_utility/b_print.c
+++ b/app/app_utility/b_print.c
@@ -255,7 +255,7 @@ int8_t b_irq_print(const char *fmt, ...)
*******************************************************************************/
int8_t b_app_print(const char *fmt, ...)
{
- uint8_t rtmp_len = 0;
+ uint16_t rtmp_len = 0;
int8_t err;
static char rtmp_buf[UART_TMP_LEN];
va_list args;
@@ -284,10 +284,10 @@ int8_t log_print(char *name, uint8_t idx, const char *fmt, ...)
{
uint8_t rtmp_len = 0;
int8_t ret;
- static char rtmp_buf[UART_TMP_LEN];
+ static char rtmp_buf[300];
va_list args;
- memset(rtmp_buf, UART_BUF_NOP, UART_TMP_LEN);
+ memset(rtmp_buf, UART_BUF_NOP, 300);
va_start(args, fmt);
if (idx == NP)
那么问题基本确认,由于上报的日志信息长度无法预计,一旦
格式信息+答题器日志 > UART_TMP_LEN(256)
就会产生越界