OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5422|回复: 1

HAL版例程USMART判断参数个数问题

[复制链接]

0

主题

0

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2022-12-29
在线时间
2 小时
发表于 2023-1-12 17:16:32 | 显示全部楼层 |阅读模式
本帖最后由 elecrui 于 2023-1-12 17:18 编辑

USMART例程下usmart_str.c文件中usmart_get_fname函数原文件第390-410行(下文代码120行-140行),在接收完函数名后计算参数个数,是通过括号中“,”个数计算的,但这里并未判断是否正在字符串内,如果参数中包含字符串,且字符串中有“,”,可能造成参数个数计算错误。
  1. /**
  2. * @brief       从str中得到函数名
  3. * [url=home.php?mod=space&uid=271674]@param[/url]       str   : 源字符串指针
  4. * @param       fname : 获取到的函数名字指针
  5. * @param       pnum  : 函数的参数个数
  6. * @param       rval  : 是否需要显示返回值(0,不需要;1,需要)
  7. * @retval      0,成功;其他,错误代码.
  8. */
  9. uint8_t usmart_get_fname(char *str, char *fname, uint8_t *pnum, uint8_t *rval)
  10. {
  11.     uint8_t res;
  12.     uint8_t fover = 0;  /* 括号深度 */
  13.     char *strtemp;
  14.     uint8_t offset = 0;
  15.     uint8_t parmnum = 0;
  16.     uint8_t temp = 1;
  17.     char fpname[6];  /* void+X+'/0' */
  18.     uint8_t fplcnt = 0; /* 第一个参数的长度计数器 */
  19.     uint8_t pcnt = 0;   /* 参数计数器 */
  20.     uint8_t nchar;
  21.     /* 判断函数是否有返回值 */
  22.     strtemp = str;

  23.     while (*strtemp != '\0')    /* 没有结束 */
  24.     {
  25.         if (*strtemp != ' ' && (pcnt & 0X7F) < 5)   /* 最多记录5个字符 */
  26.         {
  27.             if (pcnt == 0)pcnt |= 0X80; /* 置位最高位,标记开始接收返回值类型 */

  28.             if (((pcnt & 0x7f) == 4) && (*strtemp != '*'))break;    /* 最后一个字符,必须是* */

  29.             fpname[pcnt & 0x7f] = *strtemp; /* 记录函数的返回值类型 */
  30.             pcnt++;
  31.         }
  32.         else if (pcnt == 0X85)
  33.         {
  34.             break;
  35.         }

  36.         strtemp++;
  37.     }

  38.     if (pcnt)   /* 接收完了 */
  39.     {
  40.         fpname[pcnt & 0x7f] = '\0'; /* 加入结束符 */

  41.         if (usmart_strcmp(fpname, "void") == 0)
  42.         {
  43.             *rval = 0;  /* 不需要返回值 */
  44.         }
  45.         else
  46.         {
  47.             *rval = 1;  /* 需要返回值 */
  48.         }

  49.         pcnt = 0;
  50.     }

  51.     res = 0;
  52.     strtemp = str;

  53.     while (*strtemp != '(' && *strtemp != '\0')   /* 此代码找到函数名的真正起始位置 */
  54.     {
  55.         strtemp++;
  56.         res++;

  57.         if (*strtemp == ' ' || *strtemp == '*')
  58.         {
  59.             nchar = usmart_search_nextc(strtemp);   /* 获取下一个字符 */

  60.             if (nchar != '(' && nchar != '*')offset = res;  /* 跳过空格和*号 */
  61.         }
  62.     }

  63.     strtemp = str;

  64.     if (offset)strtemp += offset + 1;   /* 跳到函数名开始的地方 */

  65.     res = 0;
  66.     nchar = 0;  /* 是否正在字符串里面的标志,0,不在字符串;1,在字符串; */

  67.     while (1)
  68.     {
  69.         if (*strtemp == 0)
  70.         {
  71.             res = USMART_FUNCERR;   /* 函数错误 */
  72.             break;
  73.         }
  74.         else if (*strtemp == '(' && nchar == 0)
  75.         {
  76.             fover++;    /* 括号深度增加一级 */
  77.         }
  78.         else if (*strtemp == ')' && nchar == 0)
  79.         {
  80.             if (fover)
  81.             {
  82.                 fover--;
  83.             }
  84.             else
  85.             {
  86.                 res = USMART_FUNCERR;  /* 错误结束,没收到'(' */
  87.             }

  88.             if (fover == 0)break;       /* 到末尾了,退出 */
  89.         }
  90.         else if (*strtemp == '"')
  91.         {
  92.             nchar = !nchar;
  93.         }

  94.         if (fover == 0)   /* 函数名还没接收完 */
  95.         {
  96.             if (*strtemp != ' ')    /* 空格不属于函数名 */
  97.             {
  98.                 *fname = *strtemp;  /* 得到函数名 */
  99.                 fname++;
  100.             }
  101.         }
  102.         else     /* 已经接受完了函数名了. */
  103.         {
  104.             if (*strtemp == ',')
  105.             {
  106.                 temp = 1;           /* 使能增加一个参数 */
  107.                 pcnt++;
  108.             }
  109.             else if (*strtemp != ' ' && *strtemp != '(')
  110.             {
  111.                 if (pcnt == 0 && fplcnt < 5)    /* 当第一个参数来时,为了避免统计void类型的参数,必须做判断. */
  112.                 {
  113.                     fpname[fplcnt] = *strtemp;  /* 记录参数特征. */
  114.                     fplcnt++;
  115.                 }

  116.                 temp++;     /* 得到有效参数(非空格) */
  117.             }

  118.             if (fover == 1 && temp == 2)
  119.             {
  120.                 temp++;     /* 防止重复增加 */
  121.                 parmnum++;  /* 参数增加一个 */
  122.             }
  123.         }

  124.         strtemp++;
  125.     }

  126.     if (parmnum == 1)       /* 只有1个参数. */
  127.     {
  128.         fpname[fplcnt] = '\0';  /* 加入结束符 */

  129.         if (usmart_strcmp(fpname, "void") == 0)parmnum = 0; /* 参数为void,表示没有参数. */
  130.     }

  131.     *pnum = parmnum;/* 记录参数个数 */
  132.     *fname = '\0';  /* 加入结束符 */
  133.     return res;     /* 返回执行结果 */
  134. }
复制代码



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

10

主题

3281

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8206
金钱
8206
注册时间
2020-5-11
在线时间
3700 小时
发表于 2023-1-15 13:19:33 | 显示全部楼层
本帖最后由 LcwSwust 于 2023-1-15 13:26 编辑

虽然没用过原子的usmart,但楼主说的有道理,看来是发现了BUG。
可以试一下这些情况,比如:
fun("1,2",3)
fun("1,\"2",3)
fun(',',3)

专治疑难杂症
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 19:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表