什么是"安全"和"不安全" C / C ++中的代码?

时间:2015-08-09 00:14:40

标签: c++ c

" safe"有什么区别?和"不安全" C / C ++中的代码?

我已经读过" C ++在导致严重安全漏洞的方面是不安全的。在文章中:How Rust Compares to Other Languages and More 。什么是不安全的代码不安全?

1 个答案:

答案 0 :(得分:7)

我相信John Regehr的文章A Guide to Undefined Behavior in C and C++, Part 1很好地概述了这篇文章的内容:

  

编程语言通常区分正常   计划行动和错误行动。对于图灵完整的语言   我们无法可靠地决定某个程序是否具有潜力   执行错误;我们必须运行它并看到。

     

在安全的编程语言中,错误会在发生时被捕获。   例如,Java通过其异常系统在很大程度上是安全的。在一个   不安全的编程语言,错误没有被困。相反,之后   执行一个错误的操作,程序继续前进,但在一个   无声的错误方式可能会在以后产生可观察到的后果。   Luca Cardelli关于类型系统的文章有一个很好的清晰介绍   对这些问题。 C和C ++在强烈意义上是不安全的:执行一个   错误的操作会导致整个程序毫无意义,如   反对只有不可预测的错误操作   结果。在这些语言中,据说有错误的操作   未定义的行为。

因此,一旦我们进入未定义行为的领域,我们现在就拥有“unsafe”代码。另一篇将未定义行为视为不安全代码的好文章是What Every C Programmer Should Know About Undefined Behavior #2/3

  

在我们系列的第1部分中,我们讨论了未定义的行为是什么,以及   它如何使C和C ++编译器产生更高的性能   应用程序比“安全”语言。这篇文章谈到“不安全”的方式   C确实是,解释了一些非常令人惊讶的效果   未定义的行为可能导致。在第3部分中,我们讨论了什么是友好的   编译器可以做些什么来缓解一些意外,即使它们不是   要求。

     

我喜欢称之为“为什么未定义的行为通常是一种可怕的行为   C程序员的可怕之处“。: - )

C和C ++由它们各自的标准和we can find links to the latest ones here指定,并且那些标准将许多行为指定为未定义的行为。这基本上意味着行为是不可预测的。 C ++标准定义了未定义的行为,如下所示:

  

本国际标准没有要求的行为   [注意:当本国际标准忽略任何明确的定义时,可能会出现未定义的行为   行为或程序使用错误的构造或错误数据时。允许的未定义行为   范围从完全忽略情况与不可预测的结果,到翻译期间的行为或   程序以环境特征的文件形式执行(有或没有发行   诊断消息),终止翻译或执行(发布诊断消息)。   许多错误的程序结构不会产生未定义的行为;他们需要被诊断出来。    - 后注]

编译器不需要为未定义的行为提供诊断,我们可以找到许多未定义行为导致安全漏洞的情况,其中一个较为人知的案例可能是Linux kernel null pointer check removal

  

这个想法是寻找在C / C ++编译器时变得死的代码   关于利用未定义的行为是明智的。经典的例子   几年前在Linux内核中发现了这类错误。   代码基本上是:

struct foo *s = ...;
int x = s->f;
if (!s) return ERROR;
... use s ...
     

问题是第2行中s的取消引用允许编译器   推断s不为null(如果指针为null则为函数   未定义;编译器可以简单地忽略这种情况)。就这样   第3行中的null check得到了静默优化,现在是内核   如果攻击者可以找到一种方法来调用,则包含可利用的漏洞   这段代码带有空指针

大多数情况下,避免未定义的行为是一个良好的编码实践问题:

并使用ubsan等正确的工具,但可能会出现一些模糊的情况,例如infinite loops许多开发人员可能会感到惊讶。