【问题标题】:How to make Frama-C understand bitwise AND in tests?如何让 Frama-C 在测试中理解按位与?
【发布时间】:2013-02-07 01:12:56
【问题描述】:

我正在尝试使用 Frama-C 值分析来研究生成的大型 C 代码,其中绑定检查是使用按位与 (&) 而不是逻辑与 (&&) 完成的。例如:

int t[3];
...
if ((0 <= x) & (x < 3)) 
  t[x] = 0;

Frama-C 值分析抱怨数组访问:

warning: accessing out of bounds index [-2147483648..2147483647]. assert 0 ≤ x < 3;

通过在测试前添加断言,我设法让它对小例子感到满意:

//@ assert (x < 0 || 0<=x);
//@ assert (x < 3 || 3<=x);

并增加slevel,但我无法在实际代码中做到这一点(太大了!)。

有人知道我可以做些什么来消除这个警报吗?

(顺便说一句,有什么理由这样写测试吗?)

【问题讨论】:

  • 敬请期待,补丁正在测试中。

标签: c frama-c


【解决方案1】:

下面的补丁将使Value统一处理e1 &amp;&amp; e1c1 &amp; c2,其中c1c2是条件(但不是任意表达式)。

Index: src/value/eval_exprs.ml
===================================================================
--- src/value/eval_exprs.ml (révision 21388)
+++ src/value/eval_exprs.ml (copie de travail)
@@ -1748,11 +1748,23 @@
         reduce_by_comparison ~with_alarms reduce_rel
           cond.positive exp1 binop exp2 state

-      | true, BinOp (LAnd, exp1, exp2, _)
-      | false, BinOp (LOr, exp1, exp2, _) ->
+      | true,
+        ( BinOp (LAnd, exp1, exp2, _)
+        | BinOp (BAnd, (* 'cond1 & cond2' can be treated as 'e1 && e2' *)
+                 ({ enode = BinOp ((Le|Ne|Eq|Gt|Lt|Ge), _, _, _)} as exp1),
+                 ({ enode = BinOp ((Le|Ne|Eq|Gt|Lt|Ge), _, _, _)} as exp2),
+                 _))
+      | false,
+        ( BinOp (LOr, exp1, exp2, _)
+        | BinOp (BOr, (* '!(cond1 | cond2)' can be treated as '!(e1 || e2)' *)
+                 ({ enode = BinOp ((Le|Ne|Eq|Gt|Lt|Ge), _, _, _)} as exp1),
+                 ({ enode = BinOp ((Le|Ne|Eq|Gt|Lt|Ge), _, _, _)} as exp2),
+                 _))
+          ->
           let new_state = aux {cond with exp = exp1} state in
           let result = aux {cond with exp = exp2} new_state in
           result
+
       | false, BinOp (LAnd, exp1, exp2, _)
       | true, BinOp (LOr, exp1, exp2, _) ->
           let new_v1 = try aux {cond with exp = exp1} state

【讨论】:

  • 非常感谢!一旦我设法在我的真实代码上检查它,我会尝试并接受答案。
【解决方案2】:

在该示例中,&amp; 的两边已经是 0 或 1,因此在这种情况下使用 &amp; 而不是 &amp;&amp; 是可以的。

有什么理由这样写测试

不,我想不出他们会故意这样做的任何理由。一般来说,这是一个坏主意,因为如果稍后更改代码并且&amp; 的一侧不再是 0-1 值,那么代码就会中断。

现在是实际问题:

int t[3]; 是否也多次生成(例如在 {} 中)还是仅生成一次?如果它只定义一次,那么解决问题的方法是对其进行 malloc:int* t = malloc(3*sizeof(int))。编译器将不再抱怨。

【讨论】:

  • 感谢您的解释,但我不认为您给出的解决方案是正确的。 Frama-C 不是编译器而是静态分析器,我确实希望它在访问 t[x] 时检查 x 是否介于 0 和 3 之间。
  • 问题是,Frama 没有注意到 ((0 &lt;= x) &amp; (x &lt; 3)) 是一个有效的 0
  • @eznme 当t 指向一个大小为3 个整数的malloc 分配块时,t[x] 是一个有效的内存访问并不比t 是一个数组时更明显,所以使用malloc 不会绕过任何检查。只要 Frama-C 看不到 0 ≤ x t[x]。
  • 通常静态分析器不看malloc括号中的内容,很奇怪。也许您必须更加间接:定义一个全局(甚至可能是易变的),然后将计数(3)分配给其他地方,然后调用 malloc(thatGlobal)。这样静态分析器就不再能够计算出可用内存量。
  • @eznme Frama-C 中的分析力求正确:如果没有发出警告,则保证您的程序是安全的。相反,一旦对操作的有效性产生怀疑,他们就会报告警告。无法通过混淆程序使Anne上报的警告消失;你只会得到更多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多