简体   繁体   English

strtok_s 和编译器 C11 向前兼容

[英]strtok_s and compilers C11 onward compliance

The declaration of strtok_s in C11, and its usage, look to be very different from the strtok_s in compilers like the latest bundled with Visual Studio 2022 (17.4.4) and also GCC 12.2.0 (looking at MinGW64 distribution). C11 中strtok_s的声明及其用法看起来与编译器中的strtok_s非常不同,例如与 Visual Studio 2022 (17.4.4) 捆绑在一起的最新版本以及 GCC 12.2.0(查看 MinGW64 发行版)。

I fear the different form has been developed as a safer and accepted alternative to strtok long before C11.我担心这种不同的形式早在 C11 之前就已被开发为strtok的更安全且被接受的替代品。 What happens now if someone wants to use strtok_s and stay C11 compliant?如果有人想使用strtok_s并保持 C11 兼容,现在会发生什么?

Are the compiler supplied libraries C11 compliant?编译器提供的库是否符合 C11 标准?

Maybe it's just that I've been fooled by something otherwise obvious, and someone can help me...也许只是我被一些明显的事情所愚弄,有人可以帮助我......


This is C11 (and similar is to C17 and early drafts of C23):这是 C11(类似于 C17 和 C23 的早期草稿):

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

the same can be found as a good reference in the safec library同样可以在safec 库中找到很好的参考

While MSC/VC and GCC have the form虽然MSC/VC和 GCC 具有以下形式

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

The C11 "Annex K bounds checking interfaces" was received with a lot of scepticism and in practice nearly no standard lib implemented it. C11“附件 K 边界检查接口”受到了很多质疑,实际上几乎没有标准库实现它。 See for example Field Experience With Annex K — Bounds Checking Interfaces .请参阅附件 K 的现场经验示例 - 边界检查接口

As for the MSVC compiler, it doesn't conform to any C standard and never made such claims - you can try this out to check if you are using such a compiler or not:至于 MSVC 编译器,它不符合任何 C 标准,也从未做出这样的声明 - 你可以试试这个来检查你是否使用这样的编译器:

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

In particular, MSVC did not implement Annex K either, but already had non-standard library extensions in place prior to C11.特别是,MSVC 也没有实现 Annex K,但在 C11 之前已经有了非标准库扩展。

In practice _s means:在实践中_s意味着:

  • Possibly more safe or possibly less safe, depending on use and what the programmer expected.可能更安全也可能更不安全,这取决于使用情况和程序员的预期。
  • Non-portable.不可携带。
  • Possibly non-conforming.可能不符合要求。

If portability and standard conformance are important, then avoid _s functions.如果可移植性和标准一致性很重要,那么请避免使用_s函数。

In practice _s functions protect against two things: getting passed non-sanitized input or null pointers.在实践中, _s函数可以防止两件事:传递未净化的输入或 null 指针。 So assuming that you do proper input sanitation and don't pass null pointers to library functions, the _s functions aren't giving you extra safety, just extra execution bloat and portability problems.因此,假设您进行了适当的输入清理并且没有将 null 指针传递给库函数,那么_s函数不会给您额外的安全性,只会带来额外的执行膨胀和可移植性问题。

What happens now if someone wants to use strtok_s and stay C11 compliant?如果有人想使用strtok_s并保持 C11 兼容,现在会发生什么?

You de facto can't .事实上不能

And it's not limited to just strtok_s() .而且它不仅限于strtok_s() The entire C11 Annex K set of implementations is fractured, and because the major deviations from the standard are from Microsoft's implementation, there will probably never be a way to write portable, standard-conforming code using the Annex K functions.整个 C11 Annex K 实现集是支离破碎的,因为与标准的主要偏差来自 Microsoft 的实现,可能永远没有办法使用 Annex K 函数编写可移植的、符合标准的代码。

Per N1967 Field Experience With Annex K — Bounds Checking Interface :根据N1967 附件 K 的现场经验 - 边界检查接口

Available Implementations可用的实现

Despite the specification of the APIs having been around for over a decade only a handful of implementations exist with varying degrees of completeness and conformance.尽管 API 的规范已经存在了十多年,但只有少数实现具有不同程度的完整性和一致性。 The following is a survey of implementations that are known to exist and their status.以下是对已知存在的实施及其状态的调查。

While two of the implementations below are available in portable source code form as Open Source projects, none of the popular Open Source distribution such as BSD or Linux has chosen to make either available to their users.虽然下面的两个实现以可移植源代码形式作为开源项目提供,但没有一个流行的开源发行版(如 BSD 或 Linux)选择将其中一个提供给他们的用户。 At least one (GNU C Library) has repeatedly rejected proposals for inclusion for some of the same reasons as those noted by the Austin Group in their initial review of TR 24731-1 N1106].至少有一个(GNU C 库)一再拒绝包含的提议,原因与奥斯汀集团在他们对 TR 24731-1 N1106 的初步审查中指出的一些相同的原因。 It appears unlikely that the APIs will be provided by future versions of these distributions.这些发行版的未来版本似乎不太可能提供这些 API。

Microsoft Visual Studio微软视觉工作室

Microsoft Visual Studio implements an early version of the APIs. Microsoft Visual Studio 实现了早期版本的 API。 However, the implementation is incomplete and conforms neither to C11 nor to the original TR 24731-1.但是,该实现并不完整,既不符合 C11 也不符合原始 TR 24731-1。 For example, it doesn't provide the set_constraint_handler_s function but instead defines a _invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler) function with similar behavior but a slightly different and incompatible signature.例如,它不提供set_constraint_handler_s function 而是定义一个_invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler) function 具有类似的行为,但签名略有不同且不兼容。 It also doesn't define the abort_handler_s and ignore_handler_s functions, the memset_s function (which isn't part of the TR), or the RSIZE_MAX macro.它还没有定义abort_handler_signore_handler_s函数、 memset_s function(它不是 TR 的一部分)或RSIZE_MAX宏。 The Microsoft implementation also doesn't treat overlapping source and destination sequences as runtime-constraint violations and instead has undefined behavior in such cases. Microsoft 实现也不将重叠的源序列和目标序列视为运行时约束违规,而是在这种情况下具有未定义的行为。

As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable.由于与规范存在大量偏差,Microsoft 实施不能被视为符合规范或可移植。

... ...

Safe C Library保险箱 C 图书馆

Safe C Library [SafeC] is a fairly efficient and portable but unfortunately very incomplete implementation of Annex K with support for the string manipulation subset of functions declared in <string.h> . Safe C 库 [SafeC] 是一个相当高效和可移植但不幸的是非常不完整的 Annex K 实现,它支持<string.h>中声明的函数的字符串操作子集。

Due to its lack of support for Annex K facilities beyond the <string.h> functions the Safe C Library cannot be considered a conforming implementation.由于它不支持<string.h>函数之外的 Annex K 设施,安全 C 库不能被视为符合要求的实现。

Even the Safe C library is non-conforming.甚至 Safe C 库也不符合要求。

Whether these functions are "safer" is debatable.这些功能是否“更安全”值得商榷。 Read the entire document.阅读整个文档。

Unnecessary Uses不必要的使用

A widespread fallacy originated by Microsoft's deprecation of the standard functions in an effort to increase the adoption of the APIs is that every call to the standard functions is necessarily unsafe and should be replaced by one to the "safer" API. As a result, security-minded teams sometimes naively embark on months-long projects rewriting their working code and dutifully replacing all instances of the "deprecated" functions with the corresponding APIs.微软为了提高 API 的采用率而弃用标准函数而产生的一个普遍谬论是,对标准函数的每次调用都必然是不安全的,应该用“更安全”的 API 来代替。因此,安全有思想的团队有时会天真地开始长达数月的项目,重写他们的工作代码,并尽职尽责地用相应的 API 替换所有“已弃用”函数的实例。 This not only leads to unnecessary churn and raises the risk of injecting new bugs into correct code, it also makes the rewritten code less efficient.这不仅会导致不必要的改动并增加将新错误注入正确代码的风险,还会降低重写代码的效率。

Also, read the updated N1969 Updated Field Experience With Annex K — Bounds Checking Interfaces :此外,请阅读更新后的N1969 更新现场经验与附件 K — 边界检查接口

Despite more than a decade since the original proposal and nearly ten years since the ratification of ISO/IEC TR 24731-1:2007, and almost five years since the introduction of the Bounds checking interfaces into the C standard, no viable conforming implementations has emerged .尽管自最初提议以来已有十多年,自 ISO/IEC TR 24731-1:2007 获得批准已近十年,自将边界检查接口引入 C 标准已近五年,但仍未出现可行的合规实现. The APIs continue to be controversial and requests for implementation continue to be rejected by implementers. API 继续存在争议,实施请求继续被实施者拒绝。

The design of the Bounds checking interfaces, though well-intentioned, suffers from far too many problems to correct.边界检查接口的设计虽然用心良苦,但存在太多问题需要纠正。 Using the APIs has been seen to lead to worse quality, less secure software than relying on established approaches or modern technologies .与依赖既定方法或现代技术相比,使用 API 已被认为会导致质量更差、安全性更低的软件 More effective and less intrusive approaches have become commonplace and are often preferred by users and security experts alike.更有效和侵入性更小的方法已变得司空见惯,并且通常受到用户和安全专家的青睐。

Therefore, we propose that Annex K be either removed from the next revision of the C standard, or deprecated and then removed.因此,我们建议将 Annex K 从 C 标准的下一次修订中删除,或者弃用后再删除。

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

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