繁体   English   中英

strtok_s 和编译器 C11 向前兼容

[英]strtok_s and compilers C11 onward compliance

C11 中strtok_s的声明及其用法看起来与编译器中的strtok_s非常不同,例如与 Visual Studio 2022 (17.4.4) 捆绑在一起的最新版本以及 GCC 12.2.0(查看 MinGW64 发行版)。

我担心这种不同的形式早在 C11 之前就已被开发为strtok的更安全且被接受的替代品。 如果有人想使用strtok_s并保持 C11 兼容,现在会发生什么?

编译器提供的库是否符合 C11 标准?

也许只是我被一些明显的事情所愚弄,有人可以帮助我......


这是 C11(类似于 C17 和 C23 的早期草稿):

char *strtok_s(char * restrict s1,
    rsize_t * restrict s1max,
    const char * restrict s2,
    char ** restrict ptr);

同样可以在safec 库中找到很好的参考

虽然MSC/VC和 GCC 具有以下形式

char* strtok_s(
    char* str,
    const char* delimiters,
    char** context
);

C11“附件 K 边界检查接口”受到了很多质疑,实际上几乎没有标准库实现它。 请参阅附件 K 的现场经验示例 - 边界检查接口

至于 MSVC 编译器,它不符合任何 C 标准,也从未做出这样的声明 - 你可以试试这个来检查你是否使用这样的编译器:

#if !defined(__STDC__) || (__STDC__==0)
  #error This compiler is non-conforming.
#endif

特别是,MSVC 也没有实现 Annex K,但在 C11 之前已经有了非标准库扩展。

在实践中_s意味着:

  • 可能更安全也可能更不安全,这取决于使用情况和程序员的预期。
  • 不可携带。
  • 可能不符合要求。

如果可移植性和标准一致性很重要,那么请避免使用_s函数。

在实践中, _s函数可以防止两件事:传递未净化的输入或 null 指针。 因此,假设您进行了适当的输入清理并且没有将 null 指针传递给库函数,那么_s函数不会给您额外的安全性,只会带来额外的执行膨胀和可移植性问题。

如果有人想使用strtok_s并保持 C11 兼容,现在会发生什么?

事实上不能

而且它不仅限于strtok_s() 整个 C11 Annex K 实现集是支离破碎的,因为与标准的主要偏差来自 Microsoft 的实现,可能永远没有办法使用 Annex K 函数编写可移植的、符合标准的代码。

根据N1967 附件 K 的现场经验 - 边界检查接口

可用的实现

尽管 API 的规范已经存在了十多年,但只有少数实现具有不同程度的完整性和一致性。 以下是对已知存在的实施及其状态的调查。

虽然下面的两个实现以可移植源代码形式作为开源项目提供,但没有一个流行的开源发行版(如 BSD 或 Linux)选择将其中一个提供给他们的用户。 至少有一个(GNU C 库)一再拒绝包含的提议,原因与奥斯汀集团在他们对 TR 24731-1 N1106 的初步审查中指出的一些相同的原因。 这些发行版的未来版本似乎不太可能提供这些 API。

微软视觉工作室

Microsoft Visual Studio 实现了早期版本的 API。 但是,该实现并不完整,既不符合 C11 也不符合原始 TR 24731-1。 例如,它不提供set_constraint_handler_s function 而是定义一个_invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler) function 具有类似的行为,但签名略有不同且不兼容。 它还没有定义abort_handler_signore_handler_s函数、 memset_s function(它不是 TR 的一部分)或RSIZE_MAX宏。 Microsoft 实现也不将重叠的源序列和目标序列视为运行时约束违规,而是在这种情况下具有未定义的行为。

由于与规范存在大量偏差,Microsoft 实施不能被视为符合规范或可移植。

...

保险箱 C 图书馆

Safe C 库 [SafeC] 是一个相当高效和可移植但不幸的是非常不完整的 Annex K 实现,它支持<string.h>中声明的函数的字符串操作子集。

由于它不支持<string.h>函数之外的 Annex K 设施,安全 C 库不能被视为符合要求的实现。

甚至 Safe C 库也不符合要求。

这些功能是否“更安全”值得商榷。 阅读整个文档。

不必要的使用

微软为了提高 API 的采用率而弃用标准函数而产生的一个普遍谬论是,对标准函数的每次调用都必然是不安全的,应该用“更安全”的 API 来代替。因此,安全有思想的团队有时会天真地开始长达数月的项目,重写他们的工作代码,并尽职尽责地用相应的 API 替换所有“已弃用”函数的实例。 这不仅会导致不必要的改动并增加将新错误注入正确代码的风险,还会降低重写代码的效率。

此外,请阅读更新后的N1969 更新现场经验与附件 K — 边界检查接口

尽管自最初提议以来已有十多年,自 ISO/IEC TR 24731-1:2007 获得批准已近十年,自将边界检查接口引入 C 标准已近五年,但仍未出现可行的合规实现. API 继续存在争议,实施请求继续被实施者拒绝。

边界检查接口的设计虽然用心良苦,但存在太多问题需要纠正。 与依赖既定方法或现代技术相比,使用 API 已被认为会导致质量更差、安全性更低的软件 更有效和侵入性更小的方法已变得司空见惯,并且通常受到用户和安全专家的青睐。

因此,我们建议将 Annex K 从 C 标准的下一次修订中删除,或者弃用后再删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM