【问题积累】printf 引发的内存越界问题

printf 引发的内存越界问题

问题描述

在开发新版本的答题器的时候,总是容易应发内存越界的问题,越界之后设备显示的数据都是错乱的,且不不停有调试信息打印输出
在这里插入图片描述

问题的分析

测试的是否发现只有新的设备会引发问题,于是定位问题在新的设备引发的问题,且突变的是时候调试信息的控制字突变,于是在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)

就会产生越界

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值