为什么 strtok() 被认为不安全?

发布于 2024-11-07 08:13:09 字数 163 浏览 5 评论 0原文

strtok 的哪些功能是不安全的(就缓冲区溢出而言),我需要注意?

对我来说有点奇怪的是,Visual C++ 中的 strtok_s (“安全”)有一个额外的“上下文”参数,但看起来在其他方面是相同的......是吗?相同,还是实际上不同?

What feature(s) of strtok is unsafe (in terms of buffer overflow) that I need to watch out for?

What's a little weird to me is that strtok_s (which is "safe") in Visual C++ has an extra "context" parameter, but it looks like it's the same in other ways... is it the same, or is it actually different?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

很糊涂小朋友 2024-11-14 08:13:09

根据本文档的 strtok_s 部分:

6.7.3.1 strtok_s 函数 strtok_s 函数修复了两个问题
在 strtok 函数中:

  1. 新参数 s1max 可防止 strtok_s 存储在
    被标记化的字符串。 (字符串
    被分成代币既是
    函数的输入和输出
    strtok_s 将空字符存储到
    字符串。)
  2. 新参数 ptr 消除了静态内部状态
    防止 strtok 重入
    (第 1.1.12 款)。 (ISO/IEC 9899
    功能 wcstok 和 ISO/IEC 9945
    (POSIX) 函数 strtok_r 修复此问题
    问题相同。)

According with the strtok_s section of this document:

6.7.3.1 The strtok_s function The strtok_s function fixes two problems
in the strtok function:

  1. A new parameter, s1max, prevents strtok_s from storing outside of the
    string being tokenized. (The string
    being divided into tokens is both an
    input and output of the function since
    strtok_s stores null characters into
    the string.)
  2. A new parameter, ptr, eliminates the static internal state that
    prevents strtok from being re-entrant
    (Subclause 1.1.12). (The ISO/IEC 9899
    function wcstok and the ISO/IEC 9945
    (POSIX) function strtok_r fix this
    problem identically.)
偏闹i 2024-11-14 08:13:09

没有什么不安全的地方。您只需要了解它的工作原理以及如何使用它。编写代码和单元测试后,只需额外几分钟即可使用 valgrind 重新运行单元测试,以确保您的操作在内存范围内。手册页说明了一切:

错误

使用这些功能时要小心。如果您确实使用它们,请注意:

  • 这些函数修改它们的第一个参数。
  • 这些函数不能用于常量字符串。
  • 分隔字符的标识丢失。
  • strtok() 函数在解析时使用静态缓冲区,因此它不是线程安全的。如果这对您很重要,请使用 strtok_r()

There is nothing unsafe about it. You just need to understand how it works and how to use it. After you write your code and unit test, it only takes a couple of extra minutes to re-run the unit test with valgrind to make sure you are operating withing memory bounds. The man page says it all:

BUGS

Be cautious when using these functions. If you do use them, note that:

  • These functions modify their first argument.
  • These functions cannot be used on constant strings.
  • The identity of the delimiting character is lost.
  • The strtok() function uses a static buffer while parsing, so it's not thread safe. Use strtok_r() if this matters to you.
平定天下 2024-11-14 08:13:09

strtok 在 Visual C++ 中是安全的(但在其他地方),因为它使用线程本地存储来保存调用之间的状态。在其他地方,全局变量用于保存 strtok() 状态。

然而,即使在 VC++ 中,strtok 是线程安全的,它仍然有点奇怪 - 你不能同时在同一线程中的不同字符串上使用 strtok()。例如,这不会很好地工作:

     token = strtok( string, seps );
     while(token)
     {
        printf("token=%s\n", token)
        token2 = strtok(string2, seps);
        while(token2)  
        {
            printf("token2=%s", token2);
            token2 = strtok( NULL, seps );
        }
        token = strtok( NULL, seps );
     }

它不会很好地工作的原因 - 对于每个线程,只能在线程本地存储中保存单个状态,而这里需要 2 个状态 - 对于第一个字符串和第二个字符串。因此,虽然 strtok 对于 VC++ 来说是线程安全的,但它是不可重入的。

strtok_s(或其他地方的 strtok_r)提供了一个显式状态,并且 strtok 变得可重入。

strtok is safe in Visual C++ (but nowhere else), as it uses thread local storage to save its state between calls. Everywhere else, global variable is used to save strtok() state.

However even in VC++, where strtok is thread-safe it is still still a bit weird - you cannot use strtok()s on different strings in the same thread at the same time. For example this would not work well:

     token = strtok( string, seps );
     while(token)
     {
        printf("token=%s\n", token)
        token2 = strtok(string2, seps);
        while(token2)  
        {
            printf("token2=%s", token2);
            token2 = strtok( NULL, seps );
        }
        token = strtok( NULL, seps );
     }

The reason why it would not work well- for every thread only single state can be saved in thread local storage, and here one would need 2 states - for the first string and for the second string. So while strtok is thread-safe with VC++, it is not reentrant.

What strtok_s (or strtok_r everywhere else) provides - an explicit state, and with that strtok becomes reentrant.

带上头具痛哭 2024-11-14 08:13:09

如果您没有正确的空终止字符串;你最终会遇到缓冲区溢出。另请注意(这是我通过艰难的方式学到的东西)strtok 似乎并不关心内部字符串。具有“hello”/“world”的IE将解析“hello”/“world”,而“hello/world”将解析为“hello world”。请注意,它在 / 上分开并忽略了它位于括号内的事实。

If you do not have a properly null terminated string; you will end up in a buffer overflow. Also note (this is something that I learned the hard way) strtok does NOT seem to care about internal strings. I.E. having "hello"/"world" will parse "hello"/"world" whereas "hello/world" will parse into "hello world". Notice that it splits on the / and ignores the fact that it is within a parenthesis.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文