我正在尝试使用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有没有理由以这种方式编写测试?)
答案 0 :(得分:4)
下面的补丁会使值与e1 && e1
和c1 & c2
统一处理,其中c1
和c2
是条件(但不是任意表达式)。
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))
。编译器将不再抱怨。