“getenv… function … may be unsafe” - really?
我正在使用MSVC编译一些使用标准库函数的C代码,例如getenv(),sprintf等,并且为警告设置了/W3。 MSVC告诉我:
'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS
问题:
-
从理论上讲,与在其他平台上使用相比,为什么这是不安全的?
-
实际上在Windows上不安全吗?
-
假设我不是在编写面向安全性的代码-我应该禁用此警告还是实际上开始为一堆标准库函数起别名?
- 您是否在这里看过:stackoverflow.com/questions/4286934
-
wiki.sei.cmu.edu/confluence/display/c/…
getenv()可能是不安全的,因为对同一函数的后续调用可能会使先前返回的指针无效。结果,诸如
的用法
1 2 3
| char *a = getenv("A");
char *b = getenv("B");
/* do stuff with both a and b */ |
可能会中断,因为不能保证a那时仍然可以使用。
getenv_s()-自C11开始在C标准库中提供- getenv_s()通过立即将值复制到调用方提供的缓冲区中来避免这种情况,在此缓冲区中,调用方可以完全控制缓冲区的生存期。 dupenv_s()通过使调用方负责管理分配的缓冲区的生存期来避免这种情况。
但是,getenv_s的签名有些争议,甚至有时甚至可以从C标准中删除该功能...请参阅此报告。
-
根据co cppreference,对于C 11和更高版本,情况并非如此。调用POSIX setenv(),unsetenv()和putenv()可能会使旧结果无效,但其他对getenv的调用则不会使旧结果无效。
-
@AndrewPenkrat:C11呢?
-
@einpoklum对于C11仍然是一个问题,并在那里引入了getenv_s。但是,此问题同时具有C和C标签,而当前答案仅覆盖C语言。
-
那么,用_dupenv_s重写getenv(" environment_variable")的确切方法是什么?
getenv像不受限制的字符串缓冲区长度一样,受到了许多经典的C标准库的困扰。这就是诸如缓冲区溢出之类的安全漏洞通常源自的地方。
如果您查看getenv_s,您会看到它为返回的字符串的长度提供了明确的界限。安全开发生命周期最佳实践建议对所有编码进行推荐,这就是为什么Visual C会针对较不安全的版本发出弃用警告的原因。
请参阅MSDN和此博客文章
There was an effort by Microsoft to get the C/C++ ISO Standard Library to include the Secure CRT here, some of which was approved for C11 Annex K as noted here. That also means that getenv_s should be part of the C++17 Standard Library by reference. That said, Annex K is officially considered optional for conformance. The _s bounds-checking versions of these functions are also still a subject of some debate in the C/C++ community.
- 但是getenv()的接口没有调用方提供缓冲区。那么风险在哪里呢?只要库本身没有引入错误,即不会溢出任何东西,并确保返回以'\\0'终止的字符串-调用方是绝对安全的。还是我错过了什么?当然,返回环境字符串的长度会更好,但这与安全性无关。
-
如果在多线程环境中使用该函数,则可以在有人从中读取缓冲区时修改该缓冲区。它也不是可重入的,这意味着,如果在读取缓冲区时进行了一个函数调用,该函数调用最终还调用了getenv(),则该值可能会意外更改。