我正在使用 MSVC 编译一些使用标准库函数的 C 代码,例如和其他函数getenv()
,并设置为警告。MSVC 告诉我:sprintf
/W3
'getenv':这个函数或变量可能不安全。考虑改用 _dupenv_s。要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS
问题:
- 为什么这在理论上是不安全的——而不是在其他平台上使用?
- 实际上在 Windows 上不安全吗?
- 假设我不是在编写面向安全的代码——我应该禁用这个警告还是开始给一堆标准库函数起别名?
我正在使用 MSVC 编译一些使用标准库函数的 C 代码,例如和其他函数getenv()
,并设置为警告。MSVC 告诉我:sprintf
/W3
'getenv':这个函数或变量可能不安全。考虑改用 _dupenv_s。要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS
问题:
getenv()
可能是不安全的,因为对同一函数的后续调用可能会使先前返回的指针无效。因此,使用如
char *a = getenv("A");
char *b = getenv("B");
/* do stuff with both a and b */
可能会中断,因为不能保证a
此时仍然可用。
getenv_s()
- 自 C11 起在 C 标准库中可用 - 通过立即将值复制到调用者提供的缓冲区中来避免这种情况,调用者可以完全控制缓冲区的生命周期。dupenv_s()
通过让调用者负责管理分配的缓冲区的生命周期来避免这种情况。
但是,for 的签名getenv_s
有些争议,并且该函数甚至可能在某些时候从 C 标准中删除……请参阅此报告。
getenv
由于没有限制字符串缓冲区长度,因此与许多经典的 C 标准库一样受到影响。这就是缓冲区溢出等安全漏洞的来源。
如果您看一下,getenv_s
您会发现它对返回的字符串的长度提供了明确的限制。安全开发生命周期最佳实践建议所有编码都使用它,这就是 Visual C++ 对不太安全的版本发出弃用警告的原因。
Microsoft 努力使 C/C++ ISO 标准库在此处包含安全 CRT ,其中一些已被批准用于 C11 附件 K,如此处所述。这也意味着它
getenv_s
应该通过引用成为 C++17 标准库的一部分。也就是说,附件 K 被官方认为是可选的一致性。这些函数的_s
边界检查版本仍然是C/C++ 社区中一些争论的主题。