【发布时间】:2019-09-14 16:31:20
【问题描述】:
我的程序从一个 smt2 文件中读取约束,所有的变量都定义为一个数组。例如
(declare-fun x () (Array (_ BitVec 32) (_ BitVec 8) ) )
(declare-fun y () (Array (_ BitVec 32) (_ BitVec 8) ) )
(assert (bvslt (concat (select x (_ bv3 32) ) (concat (select x (_ bv2 32) ) (concat (select x (_ bv1 32) ) (select x (_ bv0 32) ) ) ) ) (concat (select y (_ bv3 32) ) (concat (select y (_ bv2 32) ) (concat (select y (_ bv1 32) ) (select y (_ bv0 32) ) ) ) ) ) )
(check-sat)
(exit)
省略了其他一些约束。有时求解器会给出 x 的值:
(store (store (store ((as const (Array (_ BitVec 32) (_ BitVec 8))) #xfe)
#x00000002
#x00)
#x00000001
#xff)
#x00000003
#x80)
根据定义,数组的每个元素都是一个十六进制值,所以值应该是0x8000fffe。此值超出 C++ 中整数的上限。当我将它转换回 int 时,它是一个负值。所以我猜Z3将数组定义的所有变量都视为无符号整数。 例如,如果约束是 x > y,求解器可能会给出 x = 0x8000ffe 和 y = 0x00000001。这些值满足无符号比较的约束,但是在进行有符号比较时,x为负,y为正,因此是错误的。我想知道是否有办法告诉求解器在将数字定义为数组时对它们进行签名?
已于 2019 年 9 月 14 日 22:26:43 添加 我有两个 smt2 文件,一个是
(set-logic QF_AUFBV )
(declare-fun x () (Array (_ BitVec 32) (_ BitVec 8) ) )
(declare-fun y () (Array (_ BitVec 32) (_ BitVec 8) ) )
(assert (bvslt (concat (select x (_ bv3 32) ) (concat (select x (_ bv2 32) ) (concat (select x (_ bv1 32) ) (select x (_ bv0 32) ) ) ) ) (concat (select y (_ bv3 32) ) (concat (select y (_ bv2 32) ) (concat (select y (_ bv1 32) ) (select y (_ bv0 32) ) ) ) ) ) )
(check-sat)
(exit)
约束就是 x
(set-logic QF_AUFBV )
(declare-fun x () (Array (_ BitVec 32) (_ BitVec 8) ) )
(declare-fun y () (Array (_ BitVec 32) (_ BitVec 8) ) )
(assert (let ( (?B1 (concat (select y (_ bv3 32) ) (concat (select y (_ bv2 32) ) (concat (select y (_ bv1 32) ) (select y (_ bv0 32) ) ) ) ) ) (?B2 (concat (select x (_ bv3 32) ) (concat (select x (_ bv2 32) ) (concat (select x (_ bv1 32) ) (select x (_ bv0 32) ) ) ) ) ) ) (let ( (?B3 (bvsub ?B1 ?B2 ) ) ) (and (and (and (and (and (= false (= (_ bv0 32) ?B2 ) ) (= false (= (_ bv0 32) ?B1 ) ) ) (= false (bvslt ?B1 ?B2 ) ) ) (= false (= (_ bv0 32) ?B3 ) ) ) (= false (bvslt ?B3 ?B2 ) ) ) (= (_ bv0 32) (bvsub ?B3 ?B2 ) ) ) ) ) )
(check-sat)
(exit)
这是
[(! (0 == x)),
(! (0 == y)),
(! ( y < x)),
(! (0 ==( y - x))),
(! (( y - x) < x)),
(0 ==(( y - x) - x)) ]
这些smt2文件是Klee生成的。求解器给出
x = (store (store (store ((as const (Array (_ BitVec 32) (_ BitVec 8))) #xfe)
#x00000002
#x00)
#x00000001
#xff)
#x00000003
#x80)
y = before minimize: (store (store (store ((as const (Array (_ BitVec 32) (_ BitVec 8))) #xfc)
#x00000002
#x01)
#x00000001
#xff)
#x00000003
#x00)
所以 x=0x8000fffe,y=0x0001fffc。转换为十进制,我们有 x=2147549180,y=131068。所以 y-x-x 是-4294967296,而不是十进制的 0。求解器认为它是满意的,因为 4294967296 是
1 00000000 00000000 00000000 00000000
二进制,其中“1”是第 33 位,将被删除。所以 -4294967296 在内存中被认为是 0x00。这就是我问这个问题的原因。 X 和 y 应该是整数,所以 0x8000fffe 是 -0x0000fffe,也就是 -65534。 y 是 131068。y-x-x 显然不是 0。所以就整数而言,这些值不满足约束。表达式 y - x - x 似乎是在无符号规则中计算的。
【问题讨论】: