【发布时间】:2020-05-18 14:04:18
【问题描述】:
我在一个安全关键的嵌入式 C 项目中,有一个关于检测布尔变量中的内存损坏(例如缓冲区溢出)的讨论。众所周知,在 C 语言中,“布尔”类型实际上是一个 N 位整数,这意味着它可能有 2N-2 个无效值。 例如。如果您将 FALSE 声明为 0 并将 TRUE 声明为 1(通过宏、常量或枚举),则可以说 1 是内存损坏(或错误)的后果。
所以理论上应该可以构造这样的故障捕获代码块:
if (b == TRUE) { /* Good, do something */ }
else if (b == FALSE) { /* Good, but don't do anything */ }
else { /* Memory corruption. Deal with it. */ }
或者用 switch-case 来做。状态变量和其他枚举类型是强制性的,但为布尔值做这件事肯定会增加很多代码,我的问题是 - 值得付出努力吗?
【问题讨论】:
-
考虑到内存损坏也可能用 0 或 1 覆盖
b,我怀疑这是否真的值得。有更好的方法来尝试检测内存覆盖,不需要程序员在他们执行的每一次检查中添加代码 -
如何检测其他类型变量的损坏,例如
int?他们不会同样重要,甚至更重要吗? -
一个更好的问题可能是为什么您仍在安全相关软件中使用 C90。它包含许多 C99 解决的危险:“隐式 int”、“struct hack”、可靠的整数除法等。
-
如果
b被声明为_Bool,C 标准中没有理由相信所示代码足以检测无效位模式。 C 标准没有说明如果在读取_Bool对象时,内存中的位不是用于值 0 或 1 的位,会发生什么情况。要检测无效的位模式,您应该使用指针检查内存的内容到unsigned char。如果b是除_Bool之外的某个整数类型,那么该代码可能会起作用(尽管C 标准仍然允许填充位和陷阱表示)。 -
如果您的示例代码中的
b的类型为_Bool(或bool),如果它的值不是0,那么看看您的三个分支中的哪一个被采用会很有趣或 1. 行为可能未定义。所以如果你真的需要检查这样的事情,最好完全避免使用_Bool(或bool)作为此类对象的类型。
标签: c boolean safety-critical