"安全"和"不安全"代码在C/C++中有什么区别?
我在文章《如何比较Rust与其他语言》中读到了"C++在某些方面是不安全的,这会导致严重的安全漏洞"。哪些地方的不安全代码是存在问题的?
"安全"和"不安全"代码在C/C++中有什么区别?
我在文章《如何比较Rust与其他语言》中读到了"C++在某些方面是不安全的,这会导致严重的安全漏洞"。哪些地方的不安全代码是存在问题的?
C和C++分别由它们各自的标准规定,我们可以在这里找到最新版本的链接,而这些标准留下了许多行为被指定为未定义的行为。这基本上意味着该行为是不可预测的。C++标准将未定义的行为定义如下:在我们的系列文章的第1部分中,我们讨论了什么是未定义行为,以及它如何使C和C++编译器能够生成比"安全"语言更高性能的应用程序。本文讨论了"C语言真正的不安全性质",解释了未定义行为可能导致的一些非常惊人的影响。在第3部分中,我们谈论友好编译器可以采取什么措施来减轻一些惊喜,即使他们不是必须的。
我喜欢称之为"为什么未定义行为对C程序员通常是可怕而可怕的事情"。 :-)
编译器不需要为未定义的行为提供诊断,并且我们可以找到许多导致安全漏洞的未定义行为的案例,其中一个更为知名的案例可能是Linux内核空指针检查删除。对于此国际标准未强制执行要求的行为 [注:当此国际标准省略任何明确的行为定义或程序使用错误构造或错误数据时,可能会出现未定义的行为。允许的未定义行为范围从完全忽略情况并具有不可预测的结果,到以记录环境特征方式(带或不带诊断消息)在翻译或程序执行期间表现,直至终止翻译或执行(带诊断消息)。许多错误的程序结构不会引起未定义的行为;它们需要被诊断。 —结束注释]
大多数情况下,避免未定义行为是良好编程实践的问题:The idea is to look for code that becomes dead when a C/C++ compiler is smart about exploiting undefined behavior. The classic example of this class of error was found in the Linux kernel several years ago. The code was basically:
struct foo *s = ...; int x = s->f; if (!s) return ERROR; ... use s ...
The problem is that the dereference of s in line 2 permits a compiler to infer that s is not null (if the pointer is null then the function is undefined; the compiler can simply ignore this case). Thus, the null check in line 3 gets silently optimized away and now the kernel contains an exploitable bug if an attacker can find a way to invoke this code with a null pointer