2015-08-09 97 views
0

C/C++中“安全”和“不安全”代码之间的区别是什么?什么是C/C++中的“安全”和“不安全”代码?

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

+11

C++不是不安全的;不安全的代码是不安全的,不管其写入的语言如何。 –

+2

有些语言“本质上是安全的”,并且(理论上)不允许(妥善设计和配置的)系统的完整性受到威胁。 C/C++不是其中之一。 –

+0

@HotLicks:系统的安全性实际上不应取决于程序编写的语言。那么,“系统”是什么意思?一个程序? – Olaf

回答

2

我相信约翰·雷吉汉弗的文章A Guide to Undefined Behavior in C and C++, Part 1带给你的文章是在获得很好的概述:

编程语言通常使正常 程序的行为和错误行为之间的区别。对于图灵完整语言 ,我们无法可靠地确定离线程序是否有潜在的 执行错误;我们必须运行它才能看到。

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

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

在我们的系列的第一部分,我们讨论了什么是未定义行为, 如何让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 ... 

的问题是,S的行中的解引用2只允许编译器 推断S不为空(如果该指针为空,则功能 未定义;编译器可以简单地忽略这种情况)。因此,在3线 空支票被默默优化掉,现在内核 包含一个可利用的漏洞,如果攻击者能够找到一种方法来调用 空指针

大部分时间避免不确定的验证码行为是良好的编码习惯的问题:

,并使用正确的工具,如ubsan但可以有一些模糊的情况下,如infinite loops,很多开发商可能会觉得奇怪。