def test_solution(): # Set backend b = claripy.backend_vsa solver_type = claripy.LightFrontend s = solver_type(b) VS = claripy.ValueSet si = claripy.SI(bits=32, stride=10, lower_bound=32, upper_bound=320) nose.tools.assert_true(s.solution(si, si)) nose.tools.assert_true(s.solution(si, 32)) nose.tools.assert_false(s.solution(si, 31)) si2 = claripy.SI(bits=32, stride=0, lower_bound=3, upper_bound=3) nose.tools.assert_true(s.solution(si2, si2)) nose.tools.assert_true(s.solution(si2, 3)) nose.tools.assert_false(s.solution(si2, 18)) nose.tools.assert_false(s.solution(si2, si)) vs = VS(region='global', bits=32, val=0xDEADCA7) nose.tools.assert_true(s.solution(vs, 0xDEADCA7)) nose.tools.assert_false(s.solution(vs, 0xDEADBEEF)) si = claripy.SI(bits=32, stride=0, lower_bound=3, upper_bound=3) si2 = claripy.SI(bits=32, stride=10, lower_bound=32, upper_bound=320) vs = VS(bits=32) vs.model.merge_si('global', si) vs.model.merge_si('foo', si2) nose.tools.assert_true(s.solution(vs, 3)) nose.tools.assert_true(s.solution(vs, 122)) nose.tools.assert_true(s.solution(vs, si)) nose.tools.assert_false(s.solution(vs, 18)) nose.tools.assert_false(s.solution(vs, 322))
def test_reasonable_bounds(): si = claripy.SI(bits=32, stride=1, lower_bound=-20, upper_bound=-10) b = claripy.backends.vsa assert b.max(si) == 0xfffffff6 assert b.min(si) == 0xffffffec si = claripy.SI(bits=32, stride=1, lower_bound=-20, upper_bound=10) b = claripy.backends.vsa assert b.max(si) == 0xffffffff assert b.min(si) == 0
def test_reverse(): x = claripy.SI(name="TOP", bits=64, lower_bound=0, upper_bound=0xffffffffffffffff, stride=1) # TOP y = claripy.SI(name="range", bits=64, lower_bound=0, upper_bound=1337, stride=1) # [0, 1337] r0 = x.intersection(y) r1 = x.reversed.intersection(y) r2 = x.intersection(y.reversed).reversed r3 = x.reversed.intersection(y.reversed).reversed nose.tools.assert_equal(r0._model_vsa.max, 1337) nose.tools.assert_equal(r1._model_vsa.max, 1337) nose.tools.assert_equal(r2._model_vsa.max, 1337) nose.tools.assert_equal(r3._model_vsa.max, 1337)
def find(self, addr: Union[int,Bits], data, max_search, **kwargs): # FIXME: Attempt find() on more than one region gen = self._normalize_address_type(addr, self.state.arch.bits) for region, si in gen: si = claripy.SI(to_conv=si) r, s, i = self._regions[region].find(si, data, max_search, **kwargs) # Post-process r so that it's still a ValueSet region_base_addr = self._region_base(region) r = self.state.solver.ValueSet(r.size(), region, region_base_addr, r._model_vsa) return r, s, i
def test_reverse(): x = claripy.SI(name="TOP", bits=64, lower_bound=0, upper_bound=0xffffffffffffffff, stride=1) # TOP y = claripy.SI(name="range", bits=64, lower_bound=0, upper_bound=1337, stride=1) # [0, 1337] r0 = x.intersection(y) r1 = x.reversed.intersection(y) r2 = x.intersection(y.reversed).reversed r3 = x.reversed.intersection(y.reversed).reversed nose.tools.assert_equal(r0._model_vsa.max, 1337) nose.tools.assert_equal(r1._model_vsa.max, 1337) nose.tools.assert_equal(r2._model_vsa.max, 1337) nose.tools.assert_equal(r3._model_vsa.max, 1337) # See claripy issue #95 for details. si0 = StridedInterval(name='a', bits=32, stride=0, lower_bound=0xffff0000, upper_bound=0xffff0000) si1 = StridedInterval(name='a', bits=32, stride=0, lower_bound=0xffff0001, upper_bound=0xffff0001) dsis = DiscreteStridedIntervalSet(name='b', bits=32, si_set={si0, si1}) dsis_r = dsis.reverse() solver = claripy.SolverVSA() nose.tools.assert_equal(set(solver.eval(dsis_r, 3)), {0xffff, 0x100ffff})
def test_solution(): # Set backend solver_type = claripy.SolverVSA s = solver_type() def VS(name=None, bits=None, region=None, val=None): region = 'foobar' if region is None else region return claripy.ValueSet(bits, region=region, region_base_addr=0, value=val, name=name) si = claripy.SI(bits=32, stride=10, lower_bound=32, upper_bound=320) nose.tools.assert_true(s.solution(si, si)) nose.tools.assert_true(s.solution(si, 32)) nose.tools.assert_false(s.solution(si, 31)) si2 = claripy.SI(bits=32, stride=0, lower_bound=3, upper_bound=3) nose.tools.assert_true(s.solution(si2, si2)) nose.tools.assert_true(s.solution(si2, 3)) nose.tools.assert_false(s.solution(si2, 18)) nose.tools.assert_false(s.solution(si2, si)) vs = VS(region='global', bits=32, val=0xDEADCA7) nose.tools.assert_true(s.solution(vs, 0xDEADCA7)) nose.tools.assert_false(s.solution(vs, 0xDEADBEEF)) si = claripy.SI(bits=32, stride=0, lower_bound=3, upper_bound=3) si2 = claripy.SI(bits=32, stride=10, lower_bound=32, upper_bound=320) vs = VS(bits=si.size(), region='foo', val=si._model_vsa) # vs = vs.annotate(RegionAnnotation('foo', 0, si2)) vs2 = VS(bits=si2.size(), region='foo', val=si2._model_vsa) vs = vs.union(vs2) nose.tools.assert_true(s.solution(vs, 3)) nose.tools.assert_true(s.solution(vs, 122)) nose.tools.assert_true(s.solution(vs, si)) nose.tools.assert_false(s.solution(vs, 2)) nose.tools.assert_false(s.solution(vs, 322))
def test_reversed_concat(): a = claripy.SI('a', 32, lower_bound=10, upper_bound=0x80, stride=10) b = claripy.SI('b', 32, lower_bound=1, upper_bound=0xff, stride=1) reversed_a = claripy.Reverse(a) reversed_b = claripy.Reverse(b) # First let's check if the reversing makes sense nose.tools.assert_equal(claripy.backends.vsa.min(reversed_a), 0xa000000) nose.tools.assert_equal(claripy.backends.vsa.max(reversed_a), 0x80000000) nose.tools.assert_equal(claripy.backends.vsa.min(reversed_b), 0x1000000) nose.tools.assert_equal(claripy.backends.vsa.max(reversed_b), 0xff000000) a_concat_b = claripy.Concat(a, b) nose.tools.assert_equal(a_concat_b._model_vsa._reversed, False) ra_concat_b = claripy.Concat(reversed_a, b) nose.tools.assert_equal(ra_concat_b._model_vsa._reversed, False) a_concat_rb = claripy.Concat(a, reversed_b) nose.tools.assert_equal(a_concat_rb._model_vsa._reversed, False) ra_concat_rb = claripy.Concat(reversed_a, reversed_b) nose.tools.assert_equal(ra_concat_rb._model_vsa._reversed, False)
def test_expression(): bc = claripy.backends.concrete e = claripy.BVV(0x01020304, 32) nose.tools.assert_equal(len(e), 32) r = e.reversed nose.tools.assert_equal(bc.convert(r), 0x04030201) nose.tools.assert_equal(len(r), 32) nose.tools.assert_equal([bc.convert(i) for i in r.chop(8)], [4, 3, 2, 1]) e1 = r[31:24] nose.tools.assert_equal(bc.convert(e1), 0x04) nose.tools.assert_equal(len(e1), 8) nose.tools.assert_equal(bc.convert(e1[2]), 1) nose.tools.assert_equal(bc.convert(e1[1]), 0) ee1 = e1.zero_extend(8) nose.tools.assert_equal(bc.convert(ee1), 0x0004) nose.tools.assert_equal(len(ee1), 16) ee1 = claripy.BVV(0xfe, 8).sign_extend(8) nose.tools.assert_equal(bc.convert(ee1), 0xfffe) nose.tools.assert_equal(len(ee1), 16) xe1 = [bc.convert(i) for i in e1.chop(1)] nose.tools.assert_equal(xe1, [0, 0, 0, 0, 0, 1, 0, 0]) a = claripy.BVV(1, 1) nose.tools.assert_equal(bc.convert(a + a), 2) x = claripy.BVV(1, 32) nose.tools.assert_equal(x.length, 32) y = claripy.LShR(x, 10) nose.tools.assert_equal(y.length, 32) r = claripy.BVV(0x01020304, 32) rr = r.reversed rrr = rr.reversed #nose.tools.assert_is(bc.convert(r), bc.convert(rrr)) #nose.tools.assert_is(type(bc.convert(rr)), claripy.A) nose.tools.assert_equal(bc.convert(rr), 0x04030201) nose.tools.assert_is(r.concat(rr), claripy.Concat(r, rr)) rsum = r + rr nose.tools.assert_equal(bc.convert(rsum), 0x05050505) r = claripy.BVS('x', 32) rr = r.reversed rrr = rr.reversed nose.tools.assert_is(r, rrr) # test identity nose.tools.assert_is(r, rrr) nose.tools.assert_is_not(r, rr) ii = claripy.BVS('ii', 32) ij = claripy.BVS('ij', 32) nose.tools.assert_is(ii, ii) nose.tools.assert_is_not(ii, ij) si = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100) sj = claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=10) sk = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100) nose.tools.assert_true(claripy.backends.vsa.identical(si, si)) nose.tools.assert_false(claripy.backends.vsa.identical(si, sj)) nose.tools.assert_true(claripy.backends.vsa.identical(si, sk)) nose.tools.assert_is_not(si, sj) nose.tools.assert_is_not(sj, sk) nose.tools.assert_is_not(sk, si) # test hash cache nose.tools.assert_is(a + a, a + a) # test replacement old = claripy.BVS('old', 32, explicit_name=True) new = claripy.BVS('new', 32, explicit_name=True) ooo = claripy.BVV(0, 32) old_formula = claripy.If((old + 1) % 256 == 0, old + 10, old + 20) print(old_formula.dbg_repr()) new_formula = old_formula.replace(old, new) print(new_formula.dbg_repr()) ooo_formula = new_formula.replace(new, ooo) print(ooo_formula.dbg_repr()) nose.tools.assert_not_equal(hash(old_formula), hash(new_formula)) nose.tools.assert_not_equal(hash(old_formula), hash(ooo_formula)) nose.tools.assert_not_equal(hash(new_formula), hash(ooo_formula)) nose.tools.assert_equal(old_formula.variables, {'old'}) nose.tools.assert_equal(new_formula.variables, {'new'}) nose.tools.assert_equal(ooo_formula.variables, ooo.variables) nose.tools.assert_true(old_formula.symbolic) nose.tools.assert_true(new_formula.symbolic) nose.tools.assert_true(new_formula.symbolic) nose.tools.assert_equal( str(old_formula).replace('old', 'new'), str(new_formula)) nose.tools.assert_equal(bc.convert(ooo_formula), 20) # test dict replacement old = claripy.BVS('old', 32, explicit_name=True) new = claripy.BVS('new', 32, explicit_name=True) c = (old + 10) - (old + 20) d = (old + 1) - (old + 2) cr = c.replace_dict({ (old + 10).cache_key: (old + 1), (old + 20).cache_key: (old + 2) }) nose.tools.assert_is(cr, d) # test AST collapse s = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10) b = claripy.BVV(20, 32) sb = s + b nose.tools.assert_is_instance(sb.args[0], claripy.ast.Base) bb = b + b # this was broken previously -- it was checking if type(bb.args[0]) == A, # and it wasn't, but was instead a subclass. leaving this out for now # nose.tools.assert_not_is_instance(bb.args[0], claripy.ast.Base) # ss = s+s # (see above) # nose.tools.assert_not_is_instance(ss.args[0], claripy.ast.Base) sob = s | b # for now, this is collapsed. Presumably, Fish will make it not collapse at some point nose.tools.assert_is_instance(sob.args[0], claripy.ast.Base) # make sure the AST collapses for delayed ops like reversing rb = b.reversed #nose.tools.assert_is_instance(rb.args[0], claripy.ast.Base) # TODO: Properly delay reversing: should not be eager nose.tools.assert_is_not(rb, bb) nose.tools.assert_is(rb, rb) # test some alternate bvv creation methods nose.tools.assert_is(claripy.BVV('AAAA'), claripy.BVV(0x41414141, 32)) nose.tools.assert_is(claripy.BVV('AAAA', 32), claripy.BVV(0x41414141, 32)) nose.tools.assert_is(claripy.BVV('AB'), claripy.BVV(0x4142, 16)) nose.tools.assert_is(claripy.BVV('AB', 16), claripy.BVV(0x4142, 16)) nose.tools.assert_raises(claripy.errors.ClaripyValueError, claripy.BVV, 'AB', 8)
def test_vsa(): # Set backend b = claripy.backends.vsa SI = claripy.SI VS = claripy.ValueSet BVV = claripy.BVV # Disable the use of DiscreteStridedIntervalSet claripy.vsa.strided_interval.allow_dsis = False def is_equal(ast_0, ast_1): return claripy.backends.vsa.identical(ast_0, ast_1) si1 = claripy.TSI(32, name="foo", explicit_name=True) nose.tools.assert_equal(vsa_model(si1).name, "foo") # Normalization si1 = SI(bits=32, stride=1, lower_bound=10, upper_bound=10) nose.tools.assert_equal(vsa_model(si1).stride, 0) # Integers si1 = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10) si2 = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10) si3 = claripy.SI(bits=32, stride=0, lower_bound=28, upper_bound=28) # Strided intervals si_a = claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=20) si_b = claripy.SI(bits=32, stride=2, lower_bound=-100, upper_bound=200) si_c = claripy.SI(bits=32, stride=3, lower_bound=-100, upper_bound=200) si_d = claripy.SI(bits=32, stride=2, lower_bound=50, upper_bound=60) si_e = claripy.SI(bits=16, stride=1, lower_bound=0x2000, upper_bound=0x3000) si_f = claripy.SI(bits=16, stride=1, lower_bound=0, upper_bound=255) si_g = claripy.SI(bits=16, stride=1, lower_bound=0, upper_bound=0xff) si_h = claripy.SI(bits=32, stride=0, lower_bound=0x80000000, upper_bound=0x80000000) nose.tools.assert_true(is_equal(si1, claripy.SI(bits=32, to_conv=10))) nose.tools.assert_true(is_equal(si2, claripy.SI(bits=32, to_conv=10))) nose.tools.assert_true(is_equal(si1, si2)) # __add__ si_add_1 = si1 + si2 nose.tools.assert_true(is_equal(si_add_1, claripy.SI(bits=32, stride=0, lower_bound=20, upper_bound=20))) si_add_2 = si1 + si_a nose.tools.assert_true(is_equal(si_add_2, claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=30))) si_add_3 = si_a + si_b nose.tools.assert_true(is_equal(si_add_3, claripy.SI(bits=32, stride=2, lower_bound=-90, upper_bound=220))) si_add_4 = si_b + si_c nose.tools.assert_true(is_equal(si_add_4, claripy.SI(bits=32, stride=1, lower_bound=-200, upper_bound=400))) # __add__ with overflow si_add_5 = si_h + 0xffffffff nose.tools.assert_true(is_equal(si_add_5, claripy.SI(bits=32, stride=0, lower_bound=0x7fffffff, upper_bound=0x7fffffff))) # __sub__ si_minus_1 = si1 - si2 nose.tools.assert_true(is_equal(si_minus_1, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0))) si_minus_2 = si_a - si_b nose.tools.assert_true(is_equal(si_minus_2, claripy.SI(bits=32, stride=2, lower_bound=-190, upper_bound=120))) si_minus_3 = si_b - si_c nose.tools.assert_true(is_equal(si_minus_3, claripy.SI(bits=32, stride=1, lower_bound=-300, upper_bound=300))) # __neg__ / __invert__ / bitwise not si_neg_1 = ~si1 nose.tools.assert_true(is_equal(si_neg_1, claripy.SI(bits=32, to_conv=-11))) si_neg_2 = ~si_b nose.tools.assert_true(is_equal(si_neg_2, claripy.SI(bits=32, stride=2, lower_bound=-201, upper_bound=99))) # __or__ si_or_1 = si1 | si3 nose.tools.assert_true(is_equal(si_or_1, claripy.SI(bits=32, to_conv=30))) si_or_2 = si1 | si2 nose.tools.assert_true(is_equal(si_or_2, claripy.SI(bits=32, to_conv=10))) si_or_3 = si1 | si_a # An integer | a strided interval nose.tools.assert_true(is_equal(si_or_3 , claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=30))) si_or_3 = si_a | si1 # Exchange the operands nose.tools.assert_true(is_equal(si_or_3, claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=30))) si_or_4 = si_a | si_d # A strided interval | another strided interval nose.tools.assert_true(is_equal(si_or_4, claripy.SI(bits=32, stride=2, lower_bound=50, upper_bound=62))) si_or_4 = si_d | si_a # Exchange the operands nose.tools.assert_true(is_equal(si_or_4, claripy.SI(bits=32, stride=2, lower_bound=50, upper_bound=62))) si_or_5 = si_e | si_f # nose.tools.assert_true(is_equal(si_or_5, claripy.SI(bits=16, stride=1, lower_bound=0x2000, upper_bound=0x30ff))) si_or_6 = si_e | si_g # nose.tools.assert_true(is_equal(si_or_6, claripy.SI(bits=16, stride=1, lower_bound=0x2000, upper_bound=0x30ff))) # Shifting si_shl_1 = si1 << 3 nose.tools.assert_equal(si_shl_1.size(), 32) nose.tools.assert_true(is_equal(si_shl_1, claripy.SI(bits=32, stride=0, lower_bound=80, upper_bound=80))) # Multiplication si_mul_1 = si1 * 3 nose.tools.assert_equal(si_mul_1.size(), 32) nose.tools.assert_true(is_equal(si_mul_1, claripy.SI(bits=32, stride=0, lower_bound=30, upper_bound=30))) si_mul_2 = si_a * 3 nose.tools.assert_equal(si_mul_2.size(), 32) nose.tools.assert_true(is_equal(si_mul_2, claripy.SI(bits=32, stride=6, lower_bound=30, upper_bound=60))) si_mul_3 = si_a * si_b nose.tools.assert_equal(si_mul_3.size(), 32) nose.tools.assert_true(is_equal(si_mul_3, claripy.SI(bits=32, stride=2, lower_bound=-2000, upper_bound=4000))) # Division si_div_1 = si1 / 3 nose.tools.assert_equal(si_div_1.size(), 32) nose.tools.assert_true(is_equal(si_div_1, claripy.SI(bits=32, stride=0, lower_bound=3, upper_bound=3))) si_div_2 = si_a / 3 nose.tools.assert_equal(si_div_2.size(), 32) nose.tools.assert_true(is_equal(si_div_2, claripy.SI(bits=32, stride=1, lower_bound=3, upper_bound=6))) # Modulo si_mo_1 = si1 % 3 nose.tools.assert_equal(si_mo_1.size(), 32) nose.tools.assert_true(is_equal(si_mo_1, claripy.SI(bits=32, stride=0, lower_bound=1, upper_bound=1))) si_mo_2 = si_a % 3 nose.tools.assert_equal(si_mo_2.size(), 32) nose.tools.assert_true(is_equal(si_mo_2, claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2))) # # Extracting the sign bit # # a negative integer si = claripy.SI(bits=64, stride=0, lower_bound=-1, upper_bound=-1) sb = si[63: 63] nose.tools.assert_true(is_equal(sb, claripy.SI(bits=1, to_conv=1))) # non-positive integers si = claripy.SI(bits=64, stride=1, lower_bound=-1, upper_bound=0) sb = si[63: 63] nose.tools.assert_true(is_equal(sb, claripy.SI(bits=1, stride=1, lower_bound=0, upper_bound=1))) # Extracting an integer si = claripy.SI(bits=64, stride=0, lower_bound=0x7fffffffffff0000, upper_bound=0x7fffffffffff0000) part1 = si[63 : 32] part2 = si[31 : 0] nose.tools.assert_true(is_equal(part1, claripy.SI(bits=32, stride=0, lower_bound=0x7fffffff, upper_bound=0x7fffffff))) nose.tools.assert_true(is_equal(part2, claripy.SI(bits=32, stride=0, lower_bound=0xffff0000, upper_bound=0xffff0000))) # Concatenating two integers si_concat = part1.concat(part2) nose.tools.assert_true(is_equal(si_concat, si)) # Extracting a claripy.SI si = claripy.SI(bits=64, stride=0x9, lower_bound=0x1, upper_bound=0xa) part1 = si[63 : 32] part2 = si[31 : 0] nose.tools.assert_true(is_equal(part1, claripy.SI(bits=32, stride=0, lower_bound=0x0, upper_bound=0x0))) nose.tools.assert_true(is_equal(part2, claripy.SI(bits=32, stride=9, lower_bound=1, upper_bound=10))) # Concatenating two claripy.SIs si_concat = part1.concat(part2) nose.tools.assert_true(is_equal(si_concat, si)) # Concatenating two SIs that are of different sizes si_1 = SI(bits=64, stride=1, lower_bound=0, upper_bound=0xffffffffffffffff) si_2 = SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff) si_concat = si_1.concat(si_2) nose.tools.assert_true(is_equal(si_concat, SI(bits=96, stride=1, lower_bound=0, upper_bound=0xffffffffffffffffffffffff))) # Zero-Extend the low part si_zeroextended = part2.zero_extend(32) nose.tools.assert_true(is_equal(si_zeroextended, claripy.SI(bits=64, stride=9, lower_bound=1, upper_bound=10))) # Sign-extension si_signextended = part2.sign_extend(32) nose.tools.assert_true(is_equal(si_signextended, claripy.SI(bits=64, stride=9, lower_bound=1, upper_bound=10))) # Extract from the result above si_extracted = si_zeroextended[31:0] nose.tools.assert_true(is_equal(si_extracted, claripy.SI(bits=32, stride=9, lower_bound=1, upper_bound=10))) # Union si_union_1 = si1.union(si2) nose.tools.assert_true(is_equal(si_union_1, claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10))) si_union_2 = si1.union(si3) nose.tools.assert_true(is_equal(si_union_2, claripy.SI(bits=32, stride=18, lower_bound=10, upper_bound=28))) si_union_3 = si1.union(si_a) nose.tools.assert_true(is_equal(si_union_3, claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=20))) si_union_4 = si_a.union(si_b) nose.tools.assert_true(is_equal(si_union_4, claripy.SI(bits=32, stride=2, lower_bound=-100, upper_bound=200))) si_union_5 = si_b.union(si_c) nose.tools.assert_true(is_equal(si_union_5, claripy.SI(bits=32, stride=1, lower_bound=-100, upper_bound=200))) # Intersection si_intersection_1 = si1.intersection(si1) nose.tools.assert_true(is_equal(si_intersection_1, si2)) si_intersection_2 = si1.intersection(si2) nose.tools.assert_true(is_equal(si_intersection_2, claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10))) si_intersection_3 = si1.intersection(si_a) nose.tools.assert_true(is_equal(si_intersection_3, claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10))) si_intersection_4 = si_a.intersection(si_b) nose.tools.assert_true(is_equal(si_intersection_4, claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=20))) si_intersection_5 = si_b.intersection(si_c) nose.tools.assert_true(is_equal(si_intersection_5, claripy.SI(bits=32, stride=6, lower_bound=-100, upper_bound=200))) # More intersections t0 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0x27) t1 = claripy.SI(bits=32, stride=0x7fffffff, lower_bound=0x80000002, upper_bound=1) si_is_6 = t0.intersection(t1) nose.tools.assert_true(is_equal(si_is_6, claripy.SI(bits=32, stride=0, lower_bound=1, upper_bound=1))) t2 = claripy.SI(bits=32, stride=5, lower_bound=20, upper_bound=30) t3 = claripy.SI(bits=32, stride=1, lower_bound=27, upper_bound=0xffffffff) si_is_7 = t2.intersection(t3) nose.tools.assert_true(is_equal(si_is_7, claripy.SI(bits=32, stride=0, lower_bound=30, upper_bound=30))) t4 = claripy.SI(bits=32, stride=5, lower_bound=-400, upper_bound=400) t5 = claripy.SI(bits=32, stride=1, lower_bound=395, upper_bound=-395) si_is_8 = t4.intersection(t5) nose.tools.assert_true(is_equal(si_is_8, claripy.SI(bits=32, stride=5, lower_bound=-400, upper_bound=400))) # Sign-extension si = claripy.SI(bits=1, stride=0, lower_bound=1, upper_bound=1) si_signextended = si.sign_extend(31) nose.tools.assert_true(is_equal(si_signextended, claripy.SI(bits=32, stride=0, lower_bound=0xffffffff, upper_bound=0xffffffff))) # Comparison between claripy.SI and BVV si = claripy.SI(bits=32, stride=1, lower_bound=-0x7f, upper_bound=0x7f) si._model_vsa.uninitialized = True bvv = BVV(0x30, 32) comp = (si < bvv) nose.tools.assert_true(vsa_model(comp).identical(MaybeResult())) # Better extraction # si = <32>0x1000000[0xcffffff, 0xdffffff]R si = claripy.SI(bits=32, stride=0x1000000, lower_bound=0xcffffff, upper_bound=0xdffffff) si_byte0 = si[7: 0] si_byte1 = si[15: 8] si_byte2 = si[23: 16] si_byte3 = si[31: 24] nose.tools.assert_true(is_equal(si_byte0, claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff))) nose.tools.assert_true(is_equal(si_byte1, claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff))) nose.tools.assert_true(is_equal(si_byte2, claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff))) nose.tools.assert_true(is_equal(si_byte3, claripy.SI(bits=8, stride=1, lower_bound=0xc, upper_bound=0xd))) # Optimization on bitwise-and si_1 = claripy.SI(bits=32, stride=1, lower_bound=0x0, upper_bound=0xffffffff) si_2 = claripy.SI(bits=32, stride=0, lower_bound=0x80000000, upper_bound=0x80000000) si = si_1 & si_2 nose.tools.assert_true(is_equal(si, claripy.SI(bits=32, stride=0x80000000, lower_bound=0, upper_bound=0x80000000))) si_1 = claripy.SI(bits=32, stride=1, lower_bound=0x0, upper_bound=0x7fffffff) si_2 = claripy.SI(bits=32, stride=0, lower_bound=0x80000000, upper_bound=0x80000000) si = si_1 & si_2 nose.tools.assert_true(is_equal(si, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0))) # Concatenation: concat with zeros only increases the stride si_1 = claripy.SI(bits=8, stride=0xff, lower_bound=0x0, upper_bound=0xff) si_2 = claripy.SI(bits=8, stride=0, lower_bound=0, upper_bound=0) si = si_1.concat(si_2) nose.tools.assert_true(is_equal(si, claripy.SI(bits=16, stride=0xff00, lower_bound=0, upper_bound=0xff00))) # Extract from a reversed value si_1 = claripy.SI(bits=64, stride=0xff, lower_bound=0x0, upper_bound=0xff) si_2 = si_1.reversed[63 : 56] nose.tools.assert_true(is_equal(si_2, claripy.SI(bits=8, stride=0xff, lower_bound=0x0, upper_bound=0xff))) # # ValueSet # def VS(name=None, bits=None, region=None, val=None): region = 'foobar' if region is None else region return claripy.ValueSet(bits, region=region, region_base_addr=0, value=val, name=name) vs_1 = VS(bits=32, val=0) vs_1 = vs_1.intersection(VS(bits=32, val=1)) nose.tools.assert_true(vsa_model(vs_1).is_empty) # Test merging two addresses vsa_model(vs_1)._merge_si('global', 0, vsa_model(si1)) vsa_model(vs_1)._merge_si('global', 0, vsa_model(si3)) nose.tools.assert_true(vsa_model(vs_1).get_si('global').identical(vsa_model(SI(bits=32, stride=18, lower_bound=10, upper_bound=28)))) # Length of this ValueSet nose.tools.assert_equal(len(vsa_model(vs_1)), 32) vs_1 = VS(name='boo', bits=32, val=0).intersection(VS(name='makeitempty', bits=32, val=1)) vs_2 = VS(name='foo', bits=32, val=0).intersection(VS(name='makeitempty', bits=32, val=1)) nose.tools.assert_true(claripy.backends.vsa.identical(vs_1, vs_1)) nose.tools.assert_true(claripy.backends.vsa.identical(vs_2, vs_2)) vsa_model(vs_1)._merge_si('global', 0, vsa_model(si1)) nose.tools.assert_false(claripy.backends.vsa.identical(vs_1, vs_2)) vsa_model(vs_2)._merge_si('global', 0, vsa_model(si1)) nose.tools.assert_true(claripy.backends.vsa.identical(vs_1, vs_2)) nose.tools.assert_true(claripy.backends.vsa.is_true((vs_1 & vs_2) == vs_1)) vsa_model(vs_1)._merge_si('global', 0, vsa_model(si3)) nose.tools.assert_false(claripy.backends.vsa.identical(vs_1, vs_2)) # Subtraction # Subtraction of two pointers yields a concrete value vs_1 = VS(name='foo', region='global', bits=32, val=0x400010) vs_2 = VS(name='bar', region='global', bits=32, val=0x400000) si = vs_1 - vs_2 nose.tools.assert_is(type(vsa_model(si)), StridedInterval) nose.tools.assert_true(claripy.backends.vsa.identical(si, claripy.SI(bits=32, stride=0, lower_bound=0x10, upper_bound=0x10))) # # IfProxy # si = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=0xffffffff) if_0 = claripy.If(si == 0, si, si - 1) nose.tools.assert_true(claripy.backends.vsa.identical(if_0, if_0)) nose.tools.assert_false(claripy.backends.vsa.identical(if_0, si)) # max and min on IfProxy si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff) if_0 = claripy.If(si == 0, si, si - 1) max_val = b.max(if_0) min_val = b.min(if_0) nose.tools.assert_equal(max_val, 0xffffffff) nose.tools.assert_equal(min_val, 0x00000000) # identical nose.tools.assert_true(claripy.backends.vsa.identical(if_0, if_0)) nose.tools.assert_true(claripy.backends.vsa.identical(if_0, si)) if_0_copy = claripy.If(si == 0, si, si - 1) nose.tools.assert_true(claripy.backends.vsa.identical(if_0, if_0_copy)) if_1 = claripy.If(si == 1, si, si - 1) nose.tools.assert_true(claripy.backends.vsa.identical(if_0, if_1)) si = SI(bits=32, stride=0, lower_bound=1, upper_bound=1) if_0 = claripy.If(si == 0, si, si - 1) if_0_copy = claripy.If(si == 0, si, si - 1) nose.tools.assert_true(claripy.backends.vsa.identical(if_0, if_0_copy)) if_1 = claripy.If(si == 1, si, si - 1) nose.tools.assert_false(claripy.backends.vsa.identical(if_0, if_1)) if_1 = claripy.If(si == 0, si + 1, si - 1) nose.tools.assert_true(claripy.backends.vsa.identical(if_0, if_1)) if_1 = claripy.If(si == 0, si, si) nose.tools.assert_false(claripy.backends.vsa.identical(if_0, if_1)) # if_1 = And(VS_2, IfProxy(si == 0, 0, 1)) vs_2 = VS(region='global', bits=32, val=0xFA7B00B) si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1) if_1 = (vs_2 & claripy.If(si == 0, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0), claripy.SI(bits=32, stride=0, lower_bound=0xffffffff, upper_bound=0xffffffff))) nose.tools.assert_true(claripy.backends.vsa.is_true(vsa_model(if_1.ite_excavated.args[1]) == vsa_model(VS(region='global', bits=32, val=0)))) nose.tools.assert_true(claripy.backends.vsa.is_true(vsa_model(if_1.ite_excavated.args[2]) == vsa_model(vs_2))) # if_2 = And(VS_3, IfProxy(si != 0, 0, 1) vs_3 = VS(region='global', bits=32, val=0xDEADCA7) si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1) if_2 = (vs_3 & claripy.If(si != 0, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0), claripy.SI(bits=32, stride=0, lower_bound=0xffffffff, upper_bound=0xffffffff))) nose.tools.assert_true(claripy.backends.vsa.is_true(vsa_model(if_2.ite_excavated.args[1]) == vsa_model(VS(region='global', bits=32, val=0)))) nose.tools.assert_true(claripy.backends.vsa.is_true(vsa_model(if_2.ite_excavated.args[2]) == vsa_model(vs_3)))
def test_vsa_discrete_value_set(): """ Test cases for DiscreteStridedIntervalSet. """ # Set backend b = claripy.backend_vsa s = claripy.LightFrontend(claripy.backend_vsa) #pylint:disable=unused-variable SI = claripy.StridedInterval BVV = claripy.BVV # Allow the use of DiscreteStridedIntervalSet (cuz we wanna test it!) claripy.vsa.strided_interval.allow_dsis = True # # Union # val_1 = BVV(0, 32) val_2 = BVV(1, 32) r = val_1.union(val_2) nose.tools.assert_true(isinstance(r.model, DiscreteStridedIntervalSet)) nose.tools.assert_true( r.model.collapse(), claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1)) r = r.union(BVV(3, 32)) ints = b.eval(r, 4) nose.tools.assert_equal(len(ints), 3) nose.tools.assert_equal(ints, [0, 1, 3]) # # Intersection # val_1 = BVV(0, 32) val_2 = BVV(1, 32) r = val_1.intersection(val_2) nose.tools.assert_true(isinstance(r.model, StridedInterval)) nose.tools.assert_true(r.model.is_empty) val_1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=10) val_2 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=20) val_3 = claripy.SI(bits=32, stride=1, lower_bound=15, upper_bound=50) r = val_1.union(val_2) nose.tools.assert_true(isinstance(r.model, DiscreteStridedIntervalSet)) r = r.intersection(val_3) nose.tools.assert_equal(sorted(b.eval(r, 100)), [15, 16, 17, 18, 19, 20]) # # Some logical operations # val_1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=10) val_2 = claripy.SI(bits=32, stride=1, lower_bound=5, upper_bound=20) r_1 = val_1.union(val_2) val_3 = claripy.SI(bits=32, stride=1, lower_bound=20, upper_bound=30) val_4 = claripy.SI(bits=32, stride=1, lower_bound=25, upper_bound=35) r_2 = val_3.union(val_4) nose.tools.assert_true(isinstance(r_1.model, DiscreteStridedIntervalSet)) nose.tools.assert_true(isinstance(r_2.model, DiscreteStridedIntervalSet)) # r_1 < r_2 nose.tools.assert_true(BoolResult.is_maybe(r_1 < r_2)) # r_1 <= r_2 nose.tools.assert_true(BoolResult.is_true(r_1 <= r_2)) # r_1 >= r_2 nose.tools.assert_true(BoolResult.is_maybe(r_1 >= r_2)) # r_1 > r_2 nose.tools.assert_true(BoolResult.is_false(r_1 > r_2)) # r_1 == r_2 nose.tools.assert_true(BoolResult.is_maybe(r_1 == r_2)) # r_1 != r_2 nose.tools.assert_true(BoolResult.is_maybe(r_1 != r_2)) # # Some arithmetic operations # val_1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=10) val_2 = claripy.SI(bits=32, stride=1, lower_bound=5, upper_bound=20) r_1 = val_1.union(val_2) val_3 = claripy.SI(bits=32, stride=1, lower_bound=20, upper_bound=30) val_4 = claripy.SI(bits=32, stride=1, lower_bound=25, upper_bound=35) r_2 = val_3.union(val_4) nose.tools.assert_true(isinstance(r_1.model, DiscreteStridedIntervalSet)) nose.tools.assert_true(isinstance(r_2.model, DiscreteStridedIntervalSet)) # r_1 + r_2 r = r_1 + r_2 nose.tools.assert_true(isinstance(r.model, DiscreteStridedIntervalSet)) nose.tools.assert_true(r.model.collapse().identical( SI(bits=32, stride=1, lower_bound=20, upper_bound=55).model)) # r_2 - r_1 r = r_2 - r_1 nose.tools.assert_true(isinstance(r.model, DiscreteStridedIntervalSet)) nose.tools.assert_true(r.model.collapse().identical( SI(bits=32, stride=1, lower_bound=0, upper_bound=35).model))
def test_vsa_constraint_to_si(): # Set backend b = claripy.backend_vsa s = claripy.LightFrontend(claripy.backend_vsa) #pylint:disable=unused-variable SI = claripy.SI BVV = claripy.BVV claripy.vsa.strided_interval.allow_dsis = False # # If(SI == 0, 1, 0) == 1 # s1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) == BVV(1, 1)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) != BVV( 1, 1)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s1) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.is_true(trueside_replacement[0][1] == claripy.SI( bits=32, stride=0, lower_bound=0, upper_bound=0))) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s1) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.is_true(falseside_replacement[0][1].identical( SI(bits=32, stride=1, lower_bound=1, upper_bound=2)))) # # Extract(0, 0, Concat(BVV(0, 63), If(SI == 0, 1, 0))) == 1 # s2 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.Extract( 0, 0, claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1), BVV(0, 1)))) == 1) ast_false = (claripy.Extract( 0, 0, claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1), BVV(0, 1)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s2) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.is_true(trueside_replacement[0][1].identical( SI(bits=32, stride=0, lower_bound=0, upper_bound=0)))) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s2) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.is_true(falseside_replacement[0][1].identical( SI(bits=32, stride=1, lower_bound=1, upper_bound=2)))) # # Extract(0, 0, ZeroExt(32, If(SI == 0, BVV(1, 32), BVV(0, 32)))) == 1 # s3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.Extract( 0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32), BVV(0, 32)))) == 1) ast_false = (claripy.Extract( 0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32), BVV(0, 32)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s3) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.is_true(trueside_replacement[0][1].identical( SI(bits=32, stride=0, lower_bound=0, upper_bound=0)))) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s3) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.is_true(falseside_replacement[0][1].identical( SI(bits=32, stride=1, lower_bound=1, upper_bound=2)))) # # Extract(0, 0, ZeroExt(32, If(Extract(32, 0, (SI & claripy.SI)) < 0, BVV(1, 1), BVV(0, 1)))) # s4 = claripy.SI(bits=64, stride=1, lower_bound=0, upper_bound=0xffffffffffffffff) ast_true = (claripy.Extract( 0, 0, claripy.ZeroExt( 32, claripy.If( claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32), BVV(0, 32)))) == 1) ast_false = (claripy.Extract( 0, 0, claripy.ZeroExt( 32, claripy.If( claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32), BVV( 0, 32)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s4) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.is_true(trueside_replacement[0][1].identical( SI(bits=64, stride=1, lower_bound=-0x8000000000000000, upper_bound=-1)))) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s4) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.is_true(falseside_replacement[0][1].identical( SI(bits=64, stride=1, lower_bound=0, upper_bound=0x7fffffffffffffff))))
def test_wrapped_intervals(): #SI = claripy.StridedInterval # Disable the use of DiscreteStridedIntervalSet claripy.vsa.strided_interval.allow_dsis = False # # Signedness/unsignedness conversion # si1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff) nose.tools.assert_equal(si1.model._signed_bounds(), [(0x0, 0x7fffffff), (-0x80000000, -0x1)]) nose.tools.assert_equal(si1.model._unsigned_bounds(), [(0x0, 0xffffffff)]) # # Addition # # Plain addition si1 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1) si2 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1) si3 = claripy.SI(bits=32, stride=1, lower_bound=-2, upper_bound=2) nose.tools.assert_true((si1 + si2).identical(si3)) si4 = claripy.SI(bits=32, stride=1, lower_bound=0xfffffffe, upper_bound=2) nose.tools.assert_true((si1 + si2).identical(si4)) si5 = claripy.SI(bits=32, stride=1, lower_bound=2, upper_bound=-2) nose.tools.assert_false((si1 + si2).identical(si5)) # Addition with overflowing cardinality si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe) si2 = claripy.SI(bits=8, stride=1, lower_bound=0xfe, upper_bound=0xff) nose.tools.assert_true((si1 + si2).model.is_top) # Addition that shouldn't get a TOP si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe) si2 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0) nose.tools.assert_false((si1 + si2).model.is_top) # # Subtraction # si1 = claripy.SI(bits=8, stride=1, lower_bound=10, upper_bound=15) si2 = claripy.SI(bits=8, stride=1, lower_bound=11, upper_bound=12) si3 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=4) nose.tools.assert_true((si1 - si2).identical(si3)) # # Multiplication # # integer multiplication si1 = claripy.SI(bits=32, to_conv=0xffff) si2 = claripy.SI(bits=32, to_conv=0x10000) si3 = claripy.SI(bits=32, to_conv=0xffff0000) nose.tools.assert_true((si1 * si2).identical(si3)) # intervals multiplication si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=15) si2 = claripy.SI(bits=32, stride=1, lower_bound=20, upper_bound=30) si3 = claripy.SI(bits=32, stride=1, lower_bound=200, upper_bound=450) nose.tools.assert_true((si1 * si2).identical(si3)) # # Division # # integer division si1 = claripy.SI(bits=32, to_conv=10) si2 = claripy.SI(bits=32, to_conv=5) si3 = claripy.SI(bits=32, to_conv=2) nose.tools.assert_true((si1 / si2).identical(si3)) si3 = claripy.SI(bits=32, to_conv=0) nose.tools.assert_true((si2 / si1).identical(si3)) # intervals division si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=100) si2 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=20) si3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=10) nose.tools.assert_true((si1 / si2).identical(si3)) # # Comparisons # # -1 == 0xff si1 = claripy.SI(bits=8, stride=1, lower_bound=-1, upper_bound=-1) si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff) nose.tools.assert_true(claripy.is_true(si1 == si2)) # -2 != 0xff si1 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-2) si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff) nose.tools.assert_true(claripy.is_true(si1 != si2)) # [-2, -1] < [1, 2] (signed arithmetic) si1 = claripy.SI(bits=8, stride=1, lower_bound=1, upper_bound=2) si2 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-1) nose.tools.assert_true(claripy.is_true(si2.SLT(si1))) # [-2, -1] <= [1, 2] (signed arithmetic) nose.tools.assert_true(claripy.is_true(si2.SLE(si1))) # [0xfe, 0xff] > [1, 2] (unsigned arithmetic) nose.tools.assert_true(claripy.is_true(si2.UGT(si1))) # [0xfe, 0xff] >= [1, 2] (unsigned arithmetic) nose.tools.assert_true(claripy.is_true(si2.UGE(si1)))
def test_vsa(): # Set backend b = claripy.backend_vsa SI = claripy.StridedInterval VS = claripy.ValueSet BVV = claripy.BVV # Disable the use of DiscreteStridedIntervalSet claripy.vsa.strided_interval.allow_dsis = False def is_equal(ast_0, ast_1): return ast_0.identical(ast_1) si1 = claripy.TSI(32, name="foo") nose.tools.assert_equal(si1.model.name, "foo") # Normalization si1 = SI(bits=32, stride=1, lower_bound=10, upper_bound=10) nose.tools.assert_equal(si1.model.stride, 0) # Integers si1 = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10) si2 = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10) si3 = claripy.SI(bits=32, stride=0, lower_bound=28, upper_bound=28) # Strided intervals si_a = claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=20) si_b = claripy.SI(bits=32, stride=2, lower_bound=-100, upper_bound=200) si_c = claripy.SI(bits=32, stride=3, lower_bound=-100, upper_bound=200) si_d = claripy.SI(bits=32, stride=2, lower_bound=50, upper_bound=60) si_e = claripy.SI(bits=16, stride=1, lower_bound=0x2000, upper_bound=0x3000) si_f = claripy.SI(bits=16, stride=1, lower_bound=0, upper_bound=255) si_g = claripy.SI(bits=16, stride=1, lower_bound=0, upper_bound=0xff) si_h = claripy.SI(bits=32, stride=0, lower_bound=0x80000000, upper_bound=0x80000000) nose.tools.assert_true(is_equal(si1, claripy.SI(bits=32, to_conv=10))) nose.tools.assert_true(is_equal(si2, claripy.SI(bits=32, to_conv=10))) nose.tools.assert_true(is_equal(si1, si2)) # __add__ si_add_1 = si1 + si2 nose.tools.assert_true( is_equal(si_add_1, claripy.SI(bits=32, stride=0, lower_bound=20, upper_bound=20))) si_add_2 = si1 + si_a nose.tools.assert_true( is_equal(si_add_2, claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=30))) si_add_3 = si_a + si_b nose.tools.assert_true( is_equal( si_add_3, claripy.SI(bits=32, stride=2, lower_bound=-90, upper_bound=220))) si_add_4 = si_b + si_c nose.tools.assert_true( is_equal( si_add_4, claripy.SI(bits=32, stride=1, lower_bound=-200, upper_bound=400))) # __add__ with overflow si_add_5 = si_h + 0xffffffff nose.tools.assert_true( is_equal( si_add_5, claripy.SI(bits=32, stride=0, lower_bound=0x7fffffff, upper_bound=0x7fffffff))) # __sub__ si_minus_1 = si1 - si2 nose.tools.assert_true( is_equal(si_minus_1, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0))) si_minus_2 = si_a - si_b nose.tools.assert_true( is_equal( si_minus_2, claripy.SI(bits=32, stride=2, lower_bound=-190, upper_bound=120))) si_minus_3 = si_b - si_c nose.tools.assert_true( is_equal( si_minus_3, claripy.SI(bits=32, stride=1, lower_bound=-300, upper_bound=300))) # __neg__ / __invert__ / bitwise not si_neg_1 = ~si1 nose.tools.assert_true(is_equal(si_neg_1, claripy.SI(bits=32, to_conv=-11))) si_neg_2 = ~si_b nose.tools.assert_true( is_equal( si_neg_2, claripy.SI(bits=32, stride=2, lower_bound=-201, upper_bound=99))) # __or__ si_or_1 = si1 | si3 nose.tools.assert_true(is_equal(si_or_1, claripy.SI(bits=32, to_conv=30))) si_or_2 = si1 | si2 nose.tools.assert_true(is_equal(si_or_2, claripy.SI(bits=32, to_conv=10))) si_or_3 = si1 | si_a # An integer | a strided interval nose.tools.assert_true( is_equal(si_or_3, claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=30))) si_or_3 = si_a | si1 # Exchange the operands nose.tools.assert_true( is_equal(si_or_3, claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=30))) si_or_4 = si_a | si_d # A strided interval | another strided interval nose.tools.assert_true( is_equal(si_or_4, claripy.SI(bits=32, stride=2, lower_bound=50, upper_bound=62))) si_or_4 = si_d | si_a # Exchange the operands nose.tools.assert_true( is_equal(si_or_4, claripy.SI(bits=32, stride=2, lower_bound=50, upper_bound=62))) si_or_5 = si_e | si_f # nose.tools.assert_true( is_equal( si_or_5, claripy.SI(bits=16, stride=1, lower_bound=0x2000, upper_bound=0x30ff))) si_or_6 = si_e | si_g # nose.tools.assert_true( is_equal( si_or_6, claripy.SI(bits=16, stride=1, lower_bound=0x2000, upper_bound=0x30ff))) # Shifting si_shl_1 = si1 << 3 nose.tools.assert_equal(si_shl_1.size(), 32) nose.tools.assert_true( is_equal(si_shl_1, claripy.SI(bits=32, stride=0, lower_bound=80, upper_bound=80))) # Multiplication si_mul_1 = si1 * 3 nose.tools.assert_equal(si_mul_1.size(), 32) nose.tools.assert_true( is_equal(si_mul_1, claripy.SI(bits=32, stride=0, lower_bound=30, upper_bound=30))) si_mul_2 = si_a * 3 nose.tools.assert_equal(si_mul_2.size(), 32) nose.tools.assert_true( is_equal(si_mul_2, claripy.SI(bits=32, stride=6, lower_bound=30, upper_bound=60))) si_mul_3 = si_a * si_b nose.tools.assert_equal(si_mul_3.size(), 32) nose.tools.assert_true( is_equal( si_mul_3, claripy.SI(bits=32, stride=2, lower_bound=-2000, upper_bound=4000))) # Division si_div_1 = si1 / 3 nose.tools.assert_equal(si_div_1.size(), 32) nose.tools.assert_true( is_equal(si_div_1, claripy.SI(bits=32, stride=0, lower_bound=3, upper_bound=3))) si_div_2 = si_a / 3 nose.tools.assert_equal(si_div_2.size(), 32) nose.tools.assert_true( is_equal(si_div_2, claripy.SI(bits=32, stride=1, lower_bound=3, upper_bound=6))) # Modulo si_mo_1 = si1 % 3 nose.tools.assert_equal(si_mo_1.size(), 32) nose.tools.assert_true( is_equal(si_mo_1, claripy.SI(bits=32, stride=0, lower_bound=1, upper_bound=1))) si_mo_2 = si_a % 3 nose.tools.assert_equal(si_mo_2.size(), 32) nose.tools.assert_true( is_equal(si_mo_2, claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2))) # # Extracting the sign bit # # a negative integer si = claripy.SI(bits=64, stride=0, lower_bound=-1, upper_bound=-1) sb = si[63:63] nose.tools.assert_true(is_equal(sb, claripy.SI(bits=1, to_conv=1))) # non-positive integers si = claripy.SI(bits=64, stride=1, lower_bound=-1, upper_bound=0) sb = si[63:63] nose.tools.assert_true( is_equal(sb, claripy.SI(bits=1, stride=1, lower_bound=0, upper_bound=1))) # Extracting an integer si = claripy.SI(bits=64, stride=0, lower_bound=0x7fffffffffff0000, upper_bound=0x7fffffffffff0000) part1 = si[63:32] part2 = si[31:0] nose.tools.assert_true( is_equal( part1, claripy.SI(bits=32, stride=0, lower_bound=0x7fffffff, upper_bound=0x7fffffff))) nose.tools.assert_true( is_equal( part2, claripy.SI(bits=32, stride=0, lower_bound=0xffff0000, upper_bound=0xffff0000))) # Concatenating two integers si_concat = part1.concat(part2) nose.tools.assert_true(is_equal(si_concat, si)) # Extracting a claripy.SI si = claripy.SI(bits=64, stride=0x9, lower_bound=0x1, upper_bound=0xa) part1 = si[63:32] part2 = si[31:0] nose.tools.assert_true( is_equal( part1, claripy.SI(bits=32, stride=0, lower_bound=0x0, upper_bound=0x0))) nose.tools.assert_true( is_equal(part2, claripy.SI(bits=32, stride=9, lower_bound=1, upper_bound=10))) # Concatenating two claripy.SIs si_concat = part1.concat(part2) nose.tools.assert_true(is_equal(si_concat, si)) # Zero-Extend the low part si_zeroextended = part2.zero_extend(32) nose.tools.assert_true( is_equal(si_zeroextended, claripy.SI(bits=64, stride=9, lower_bound=1, upper_bound=10))) # Sign-extension si_signextended = part2.sign_extend(32) nose.tools.assert_true( is_equal(si_signextended, claripy.SI(bits=64, stride=9, lower_bound=1, upper_bound=10))) # Extract from the result above si_extracted = si_zeroextended[31:0] nose.tools.assert_true( is_equal(si_extracted, claripy.SI(bits=32, stride=9, lower_bound=1, upper_bound=10))) # Union si_union_1 = si1.union(si2) nose.tools.assert_true( is_equal(si_union_1, claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10))) si_union_2 = si1.union(si3) nose.tools.assert_true( is_equal( si_union_2, claripy.SI(bits=32, stride=18, lower_bound=10, upper_bound=28))) si_union_3 = si1.union(si_a) nose.tools.assert_true( is_equal(si_union_3, claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=20))) si_union_4 = si_a.union(si_b) nose.tools.assert_true( is_equal( si_union_4, claripy.SI(bits=32, stride=2, lower_bound=-100, upper_bound=200))) si_union_5 = si_b.union(si_c) nose.tools.assert_true( is_equal( si_union_5, claripy.SI(bits=32, stride=1, lower_bound=-100, upper_bound=200))) # Intersection si_intersection_1 = si1.intersection(si1) nose.tools.assert_true(is_equal(si_intersection_1, si2)) si_intersection_2 = si1.intersection(si2) nose.tools.assert_true( is_equal(si_intersection_2, claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10))) si_intersection_3 = si1.intersection(si_a) nose.tools.assert_true( is_equal(si_intersection_3, claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10))) si_intersection_4 = si_a.intersection(si_b) nose.tools.assert_true( is_equal(si_intersection_4, claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=20))) si_intersection_5 = si_b.intersection(si_c) nose.tools.assert_true( is_equal( si_intersection_5, claripy.SI(bits=32, stride=6, lower_bound=-100, upper_bound=200))) # Sign-extension si = claripy.SI(bits=1, stride=0, lower_bound=1, upper_bound=1) si_signextended = si.sign_extend(31) nose.tools.assert_true( is_equal( si_signextended, claripy.SI(bits=32, stride=0, lower_bound=0xffffffff, upper_bound=0xffffffff))) # Comparison between claripy.SI and BVV si = claripy.SI(bits=32, stride=1, lower_bound=-0x7f, upper_bound=0x7f) si.uninitialized = True bvv = BVV(0x30, 32) comp = (si < bvv) nose.tools.assert_equal(comp.model, MaybeResult()) # Better extraction # si = <32>0x1000000[0xcffffff, 0xdffffff]R si = claripy.SI(bits=32, stride=0x1000000, lower_bound=0xcffffff, upper_bound=0xdffffff) si_byte0 = si[7:0] si_byte1 = si[15:8] si_byte2 = si[23:16] si_byte3 = si[31:24] nose.tools.assert_true( is_equal( si_byte0, claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff))) nose.tools.assert_true( is_equal( si_byte1, claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff))) nose.tools.assert_true( is_equal( si_byte2, claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff))) nose.tools.assert_true( is_equal( si_byte3, claripy.SI(bits=8, stride=1, lower_bound=0xc, upper_bound=0xd))) # Optimization on bitwise-and si_1 = claripy.SI(bits=32, stride=1, lower_bound=0x0, upper_bound=0xffffffff) si_2 = claripy.SI(bits=32, stride=0, lower_bound=0x80000000, upper_bound=0x80000000) si = si_1 & si_2 nose.tools.assert_true( is_equal( si, claripy.SI(bits=32, stride=0x80000000, lower_bound=0, upper_bound=0x80000000))) si_1 = claripy.SI(bits=32, stride=1, lower_bound=0x0, upper_bound=0x7fffffff) si_2 = claripy.SI(bits=32, stride=0, lower_bound=0x80000000, upper_bound=0x80000000) si = si_1 & si_2 nose.tools.assert_true( is_equal(si, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0))) # # ValueSet # vs_1 = claripy.ValueSet(bits=32) nose.tools.assert_true(vs_1.model.is_empty, True) # Test merging two addresses vs_1.model.merge_si('global', si1) vs_1.model.merge_si('global', si3) nose.tools.assert_true( vs_1.model.get_si('global').identical( SI(bits=32, stride=18, lower_bound=10, upper_bound=28).model)) # Length of this ValueSet nose.tools.assert_equal(len(vs_1.model), 32) vs_1 = claripy.ValueSet(name='boo', bits=32) vs_2 = claripy.ValueSet(name='boo', bits=32) nose.tools.assert_true(vs_1.identical(vs_1)) nose.tools.assert_true(vs_1.identical(vs_2)) vs_1.model.merge_si('global', si1) nose.tools.assert_false(vs_1.identical(vs_2)) vs_2.model.merge_si('global', si1) nose.tools.assert_true(vs_1.identical(vs_2)) vs_1.model.merge_si('global', si3) nose.tools.assert_false(vs_1.identical(vs_2)) # # IfProxy # # max and min on IfProxy si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff) if_0 = claripy.If(si == 0, si, si - 1) max_val = b.max(if_0) min_val = b.min(if_0) nose.tools.assert_true(max_val, 0xffffffff) nose.tools.assert_true(min_val, -0x80000000) # if_1 = And(VS_2, IfProxy(si == 0, 0, 1)) vs_2 = VS(region='global', bits=32, val=0xFA7B00B) si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1) if_1 = (vs_2 & claripy.If( si == 0, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0), claripy.SI( bits=32, stride=0, lower_bound=0xffffffff, upper_bound=0xffffffff))) nose.tools.assert_true( claripy.is_true( if_1.model.trueexpr == VS(region='global', bits=32, val=0).model)) nose.tools.assert_true(claripy.is_true(if_1.model.falseexpr == vs_2.model)) # if_2 = And(VS_3, IfProxy(si != 0, 0, 1) vs_3 = claripy.ValueSet(region='global', bits=32, val=0xDEADCA7) si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1) if_2 = (vs_3 & claripy.If( si != 0, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0), claripy.SI( bits=32, stride=0, lower_bound=0xffffffff, upper_bound=0xffffffff))) nose.tools.assert_true( claripy.is_true( if_2.model.trueexpr == VS(region='global', bits=32, val=0).model)) nose.tools.assert_true(claripy.is_true(if_2.model.falseexpr == vs_3.model)) # Something crazy is gonna happen... if_3 = if_1 + if_2 nose.tools.assert_true(claripy.is_true(if_3.model.trueexpr == vs_3.model)) nose.tools.assert_true(claripy.is_true(if_3.model.falseexpr == vs_2.model))
def test_join(): # Set backend b = claripy.backend_vsa claripy.solver_backends = [] SI = claripy.StridedInterval a = claripy.SI(bits=8, to_conv=2) b = claripy.SI(bits=8, to_conv=10) c = claripy.SI(bits=8, to_conv=120) d = claripy.SI(bits=8, to_conv=130) e = claripy.SI(bits=8, to_conv=132) f = claripy.SI(bits=8, to_conv=135) # union a, b, c, d, e => [2, 132] with a stride of 2 tmp1 = a.union(b) nose.tools.assert_true( tmp1.identical(SI(bits=8, stride=8, lower_bound=2, upper_bound=10))) tmp2 = tmp1.union(c) nose.tools.assert_true( tmp2.identical(SI(bits=8, stride=2, lower_bound=2, upper_bound=120))) tmp3 = tmp2.union(d).union(e) nose.tools.assert_true( tmp3.identical(SI(bits=8, stride=2, lower_bound=2, upper_bound=132))) # union a, b, c, d, e, f => [2, 135] with a stride of 1 tmp = a.union(b).union(c).union(d).union(e).union(f) nose.tools.assert_true( tmp.identical(SI(bits=8, stride=1, lower_bound=2, upper_bound=135))) a = claripy.SI(bits=8, to_conv=1) b = claripy.SI(bits=8, to_conv=10) c = claripy.SI(bits=8, to_conv=120) d = claripy.SI(bits=8, to_conv=130) e = claripy.SI(bits=8, to_conv=132) f = claripy.SI(bits=8, to_conv=135) g = claripy.SI(bits=8, to_conv=220) h = claripy.SI(bits=8, to_conv=50) # union a, b, c, d, e, f, g, h => [220, 135] with a stride of 1 tmp = a.union(b).union(c).union(d).union(e).union(f).union(g).union(h) nose.tools.assert_true( tmp.identical(SI(bits=8, stride=1, lower_bound=220, upper_bound=135))) nose.tools.assert_true(220 in tmp.model.eval(255)) nose.tools.assert_true(225 in tmp.model.eval(255)) nose.tools.assert_true(0 in tmp.model.eval(255)) nose.tools.assert_true(135 in tmp.model.eval(255)) nose.tools.assert_false(138 in tmp.model.eval(255))
def _find(self, start, what, max_search=None, max_symbolic_bytes=None, default=None): if max_search is None: max_search = DEFAULT_MAX_SEARCH if isinstance(start, (int, long)): start = self.state.BVV(start, self.state.arch.bits) constraints = [ ] remaining_symbolic = max_symbolic_bytes seek_size = len(what)/8 symbolic_what = self.state.se.symbolic(what) l.debug("Search for %d bytes in a max of %d...", seek_size, max_search) preload = True all_memory = self.load(start, max_search, endness="Iend_BE") if all_memory.symbolic: preload = False cases = [ ] match_indices = [ ] offsets_matched = [ ] # Only used in static mode for i in itertools.count(): l.debug("... checking offset %d", i) if i > max_search - seek_size: l.debug("... hit max size") break if remaining_symbolic is not None and remaining_symbolic == 0: l.debug("... hit max symbolic") break if preload: b = all_memory[max_search*8 - i*8 - 1 : max_search*8 - i*8 - seek_size*8] else: b = self.load(start + i, seek_size, endness="Iend_BE") cases.append([b == what, start + i]) match_indices.append(i) if self.state.mode == 'static': # In static mode, nothing is symbolic if isinstance(b.model, claripy.vsa.StridedInterval): si = b if not si.intersection(what).model.is_empty: offsets_matched.append(start + i) if si.identical(what): break if si.model.cardinality != 1: if remaining_symbolic is not None: remaining_symbolic -= 1 elif type(b.model) in (claripy.bv.BVV, int, long): si = claripy.SI(bits=8, to_conv=b.model) if not si.intersection(what).model.is_empty: offsets_matched.append(start + i) if si.identical(what): break else: # Comparison with other types (like IfProxy or ValueSet) is not supported if remaining_symbolic is not None: remaining_symbolic -= 1 else: # other modes (e.g. symbolic mode) if not b.symbolic and not symbolic_what: #print "... checking", b, 'against', what if self.state.se.any_int(b) == self.state.se.any_int(what): l.debug("... found concrete") break else: if remaining_symbolic is not None: remaining_symbolic -= 1 if self.state.mode == 'static': r = self.state.se.ESI(self.state.arch.bits) for off in offsets_matched: r = r.union(off) constraints = [ ] return r, constraints, match_indices # TODO: Should we return match_indices? else: if default is None: l.debug("... no default specified") default = 0 constraints += [ self.state.se.Or(*[ c for c,_ in cases]) ] #l.debug("running ite_cases %s, %s", cases, default) r = self.state.se.ite_cases(cases, default) return r, constraints, match_indices
def test_wrapped_intervals(): #SI = claripy.StridedInterval # Disable the use of DiscreteStridedIntervalSet claripy.vsa.strided_interval.allow_dsis = False # # Signedness/unsignedness conversion # si1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff) nose.tools.assert_equal(vsa_model(si1)._signed_bounds(), [ (0x0, 0x7fffffff), (-0x80000000, -0x1) ]) nose.tools.assert_equal(vsa_model(si1)._unsigned_bounds(), [ (0x0, 0xffffffff) ]) # # Pole-splitting # # south-pole splitting si1 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1) si_list = vsa_model(si1)._ssplit() nose.tools.assert_equal(len(si_list), 2) nose.tools.assert_true( si_list[0].identical(vsa_model(claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=-1)))) nose.tools.assert_true( si_list[1].identical(vsa_model(claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1)))) # north-pole splitting si1 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=-3) si_list = vsa_model(si1)._nsplit() nose.tools.assert_equal(len(si_list), 2) nose.tools.assert_true( si_list[0].identical(vsa_model(claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=0x7fffffff)))) nose.tools.assert_true( si_list[1].identical(vsa_model(claripy.SI(bits=32, stride=1, lower_bound=0x80000000, upper_bound=-3)))) # north-pole splitting, episode 2 si1 = claripy.SI(bits=32, stride=3, lower_bound=3, upper_bound=0) si_list = vsa_model(si1)._nsplit() nose.tools.assert_equal(len(si_list), 2) nose.tools.assert_true( si_list[0].identical(vsa_model(claripy.SI(bits=32, stride=3, lower_bound=3, upper_bound=0x7ffffffe)))) nose.tools.assert_true( si_list[1].identical(vsa_model(claripy.SI(bits=32, stride=3, lower_bound=0x80000001, upper_bound=0)))) # bipolar splitting si1 = claripy.SI(bits=32, stride=1, lower_bound=-2, upper_bound=-8) si_list = vsa_model(si1)._psplit() nose.tools.assert_equal(len(si_list), 3) nose.tools.assert_true( si_list[0].identical(vsa_model(claripy.SI(bits=32, stride=1, lower_bound=-2, upper_bound=-1)))) nose.tools.assert_true( si_list[1].identical(vsa_model(claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0x7fffffff)))) nose.tools.assert_true( si_list[2].identical(vsa_model(claripy.SI(bits=32, stride=1, lower_bound=0x80000000, upper_bound=-8)))) # # Addition # # Plain addition si1 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1) si2 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1) si3 = claripy.SI(bits=32, stride=1, lower_bound=-2, upper_bound=2) nose.tools.assert_true(claripy.backends.vsa.identical(si1 + si2, si3)) si4 = claripy.SI(bits=32, stride=1, lower_bound=0xfffffffe, upper_bound=2) nose.tools.assert_true(claripy.backends.vsa.identical(si1 + si2, si4)) si5 = claripy.SI(bits=32, stride=1, lower_bound=2, upper_bound=-2) nose.tools.assert_false(claripy.backends.vsa.identical(si1 + si2, si5)) # Addition with overflowing cardinality si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe) si2 = claripy.SI(bits=8, stride=1, lower_bound=0xfe, upper_bound=0xff) nose.tools.assert_true(vsa_model((si1 + si2)).is_top) # Addition that shouldn't get a TOP si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe) si2 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0) nose.tools.assert_false(vsa_model((si1 + si2)).is_top) # # Subtraction # si1 = claripy.SI(bits=8, stride=1, lower_bound=10, upper_bound=15) si2 = claripy.SI(bits=8, stride=1, lower_bound=11, upper_bound=12) si3 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=4) nose.tools.assert_true(claripy.backends.vsa.identical(si1 - si2, si3)) # # Multiplication # # integer multiplication si1 = claripy.SI(bits=32, to_conv=0xffff) si2 = claripy.SI(bits=32, to_conv=0x10000) si3 = claripy.SI(bits=32, to_conv=0xffff0000) nose.tools.assert_true(claripy.backends.vsa.identical(si1 * si2, si3)) # intervals multiplication si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=15) si2 = claripy.SI(bits=32, stride=1, lower_bound=20, upper_bound=30) si3 = claripy.SI(bits=32, stride=1, lower_bound=200, upper_bound=450) nose.tools.assert_true(claripy.backends.vsa.identical(si1 * si2, si3)) # # Division # # integer division si1 = claripy.SI(bits=32, to_conv=10) si2 = claripy.SI(bits=32, to_conv=5) si3 = claripy.SI(bits=32, to_conv=2) nose.tools.assert_true(claripy.backends.vsa.identical(si1 / si2, si3)) si3 = claripy.SI(bits=32, to_conv=0) nose.tools.assert_true(claripy.backends.vsa.identical(si2 / si1, si3)) # intervals division si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=100) si2 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=20) si3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=10) nose.tools.assert_true(claripy.backends.vsa.identical(si1 / si2, si3)) # # Extension # # zero-extension si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfd) si_zext = si1.zero_extend(32 - 8) si_zext_ = claripy.SI(bits=32, stride=1, lower_bound=0x0, upper_bound=0xfd) nose.tools.assert_true(claripy.backends.vsa.identical(si_zext, si_zext_)) # sign-extension si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfd) si_sext = si1.sign_extend(32 - 8) si_sext_ = claripy.SI(bits=32, stride=1, lower_bound=0xffffff80, upper_bound=0x7f) nose.tools.assert_true(claripy.backends.vsa.identical(si_sext, si_sext_)) # # Comparisons # # -1 == 0xff si1 = claripy.SI(bits=8, stride=1, lower_bound=-1, upper_bound=-1) si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff) nose.tools.assert_true(claripy.backends.vsa.is_true(si1 == si2)) # -2 != 0xff si1 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-2) si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff) nose.tools.assert_true(claripy.backends.vsa.is_true(si1 != si2)) # [-2, -1] < [1, 2] (signed arithmetic) si1 = claripy.SI(bits=8, stride=1, lower_bound=1, upper_bound=2) si2 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-1) nose.tools.assert_true(claripy.backends.vsa.is_true(si2.SLT(si1))) # [-2, -1] <= [1, 2] (signed arithmetic) nose.tools.assert_true(claripy.backends.vsa.is_true(si2.SLE(si1))) # [0xfe, 0xff] > [1, 2] (unsigned arithmetic) nose.tools.assert_true(claripy.backends.vsa.is_true(si2.UGT(si1))) # [0xfe, 0xff] >= [1, 2] (unsigned arithmetic) nose.tools.assert_true(claripy.backends.vsa.is_true(si2.UGE(si1)))
def test_vsa_constraint_to_si(): # Set backend b = claripy.backends.vsa s = claripy.SolverVSA() #pylint:disable=unused-variable SI = claripy.SI BVV = claripy.BVV claripy.vsa.strided_interval.allow_dsis = False # # If(SI == 0, 1, 0) == 1 # s1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) == BVV(1, 1)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) != BVV(1, 1)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s1) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.is_true(trueside_replacement[0][1] == claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0))) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s1) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # If(SI == 0, 1, 0) <= 1 # s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) <= BVV(1, 1)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) > BVV(1, 1)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) # Always satisfiable falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, False) # Not sat # # If(SI == 0, 20, 10) > 15 # s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(20, 32), BVV(10, 32)) > BVV(15, 32)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(20, 32), BVV(10, 32)) <= BVV(15, 32)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s1) # True side: SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s1) # False side; SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # If(SI == 0, 20, 10) >= 15 # s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(15, 32), BVV(10, 32)) >= BVV(15, 32)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(15, 32), BVV(10, 32)) < BVV(15, 32)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s1) # True side: SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s1) # False side; SI<32>0[0,0] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # Extract(0, 0, Concat(BVV(0, 63), If(SI == 0, 1, 0))) == 1 # s2 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.Extract(0, 0, claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1), BVV(0, 1)))) == 1) ast_false = (claripy.Extract(0, 0, claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1), BVV(0, 1)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s2) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s2) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # Extract(0, 0, ZeroExt(32, If(SI == 0, BVV(1, 32), BVV(0, 32)))) == 1 # s3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32), BVV(0, 32)))) == 1) ast_false = (claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32), BVV(0, 32)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s3) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s3) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # Extract(0, 0, ZeroExt(32, If(Extract(32, 0, (SI & claripy.SI)) < 0, BVV(1, 1), BVV(0, 1)))) # s4 = claripy.SI(bits=64, stride=1, lower_bound=0, upper_bound=0xffffffffffffffff) ast_true = ( claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32), BVV(0, 32)))) == 1) ast_false = ( claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32), BVV(0, 32)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s4[31:0]) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=1, lower_bound=-0x80000000, upper_bound=-1)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s4[31:0]) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=0, upper_bound=0x7fffffff)) ) # # TOP_SI != -1 # s5 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff) ast_true = (s5 == claripy.SI(bits=32, stride=1, lower_bound=0xffffffff, upper_bound=0xffffffff)) ast_false = (s5 != claripy.SI(bits=32, stride=1, lower_bound=0xffffffff, upper_bound=0xffffffff)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_true(trueside_sat) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s5) nose.tools.assert_true(claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=1, lower_bound=0xffffffff, upper_bound=0xffffffff) ) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_true(falseside_sat) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s5) nose.tools.assert_true(claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=0, upper_bound=0xfffffffe) ) )