为什么 strtok() 被认为不安全?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据本文档的 strtok_s 部分:
According with the strtok_s section of this document:
没有什么不安全的地方。您只需要了解它的工作原理以及如何使用它。编写代码和单元测试后,只需额外几分钟即可使用 valgrind 重新运行单元测试,以确保您的操作在内存范围内。手册页说明了一切:
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:
strtok 在 Visual C++ 中是安全的(但在其他地方),因为它使用线程本地存储来保存调用之间的状态。在其他地方,全局变量用于保存 strtok() 状态。
然而,即使在 VC++ 中,strtok 是线程安全的,它仍然有点奇怪 - 你不能同时在同一线程中的不同字符串上使用 strtok()。例如,这不会很好地工作:
它不会很好地工作的原因 - 对于每个线程,只能在线程本地存储中保存单个状态,而这里需要 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:
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.
如果您没有正确的空终止字符串;你最终会遇到缓冲区溢出。另请注意(这是我通过艰难的方式学到的东西)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.