如何使Frama-C在测试中理解按位AND?

时间:2013-02-06 16:17:22

标签: c frama-c

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

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,但我不能在实际代码中执行此操作(太大了!)。

是否有人知道我可以做些什么来消除此警报?

(BTW有没有理由以这种方式编写测试?)

2 个答案:

答案 0 :(得分:4)

下面的补丁会使值与e1 && e1c1 & 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

答案 1 :(得分:1)

在该示例中,&的两边已经是0或1,因此在这种情况下使用&代替&&是正常的。

  

有没有理由以这种方式编写测试

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

现在转到实际问题:

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