【问题标题】:How could strtok store outside of the string argument?strtok 如何存储在字符串参数之外?
【发布时间】:2020-07-08 12:09:59
【问题描述】:

strtok_s 函数 (C11) 解决的两个问题之一是它防止存储在输入字符串之外。据我了解,只有将非空终止字符串传递给strtok,这才有可能。

如果我只将正确的以空结尾的字符串传递给strtok,那么它是否没有写入输入字符串之外的风险?

【问题讨论】:

  • 如果不是这样,该函数将不会包含在 C 标准中。
  • "...在外面写的风险..." 你的意思是问外面的阅读吗? strtok 根本不进行任何写入,即使在输入字符串中也是如此。
  • @ArthurTacca 你错了。该函数更改输入字符串。
  • @VladfromMoscow 哎呀你是对的,我错了。很抱歉造成混乱。
  • 请在使用任何可选的附件 K 函数之前阅读Field Experience With Annex K — Bounds Checking Interfaces,因为它们并不能真正使您的代码更安全。请特别注意这部分:“由于与规范存在大量偏差,因此不能将 Microsoft 实现视为符合标准或可移植。”

标签: c strtok c11


【解决方案1】:

让我们开始回答主要问题,关于strtok 写入超出包含字符串的缓冲区的大小。

  1. strtok 实际上修改了输入字符串:它在原来的分隔符处写入了一个字符串终止符 ('\0')。通过这种方式,它可以返回给用户以 null 结尾的令牌
  2. 如果提供了错误输入(其中缺少字符串终止符的缓冲区),它可能会写入超出输入缓冲区大小的内容。它将读取直到在内存中找到'\0',如果在到达末尾之前找到分隔符,则写入数据

现在,我们不能正确地说 "strtok_s 防止存储在输入字符串之外",但我们可以说这个函数提供了一种控制输入字符串字节数的方法被检查,因此书面(如上所述)。

我们正在谈论的控件与使用strncpy而不是strcpy的控件相同:如果输入字符串避免内存损坏,我们可以将最大大小传递给strtok_s在缺少字符串终止符的情况下

我们来看看strtok_s()签名:

char *strtok_s(char *restrict str, rsize_t *restrict strmax,
               const char *restrict delim, char **restrict ptr);

对比strtok的界面,我们多了两个参数。 ptr 参数对于使其可重入很有用,并且它也存在于 strtok_r 中。它与这个问题没有直接关系。

strmax 参数是我们正在寻找的参数

strmax - 指向一个对象的指针最初拥有str的大小:strtok_s 存储有待检查的字符数

(重点是我的)。

因此,将指向变量的指针传递给strmax,该变量使用包含输入字符串的字符缓冲区的大小进行初始化,将确保永远不会发生超出该大小的写入。

【讨论】:

  • 这就是我的想法。 strmax 参数本质上扩展了 strtok 以允许任意字符数组作为输入,而不仅仅是以空字符结尾的字符串。
  • @cholz 我也编辑直接回答你的标题问题
猜你喜欢
  • 2023-03-10
  • 1970-01-01
  • 2021-02-02
  • 2019-08-22
  • 1970-01-01
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多