def _op_generic_Ctz(self, args): """Count the trailing zeroes""" wtf_expr = claripy.BVV(self._from_size, self._from_size) for a in reversed(range(self._from_size)): bit = claripy.Extract(a, a, args[0]) wtf_expr = claripy.If(bit == 1, claripy.BVV(a, self._from_size), wtf_expr) return wtf_expr
def _op_generic_Clz(self, args): """Count the leading zeroes""" piece_size = len(args[0]) wtf_expr = claripy.BVV(piece_size, piece_size) for a in range(piece_size): bit = claripy.Extract(a, a, args[0]) wtf_expr = claripy.If(bit==1, claripy.BVV(piece_size-a-1, piece_size), wtf_expr) return wtf_expr
def _op_generic_Clz(self, args): '''Count the leading zeroes''' wtf_expr = claripy.BVV(self._from_size, self._from_size) for a in range(self._from_size): bit = claripy.Extract(a, a, args[0]) wtf_expr = claripy.If( bit == 1, claripy.BVV(self._from_size - a - 1, self._from_size), wtf_expr) return wtf_expr
def _op_vector_float_mapped(self, args): rm_part = [] if self._generic_name in self.NO_RM else [args[0]] chopped_args = ( [ claripy.Extract((i + 1) * self._vector_size - 1, i * self._vector_size, a).raw_to_fp() for a in (args if self._generic_name in self.NO_RM else args[1:]) ] for i in reversed(range(self._vector_count)) ) return claripy.Concat(*(self._op_float_mapped(rm_part + ca).raw_to_bv() for ca in chopped_args))
def test_extract_zeroext(): x = claripy.BVS('x', 8) expr = claripy.Extract(31, 0, claripy.ZeroExt(56, x)) <= claripy.BVV( 0xe, 32) s, r = claripy.balancer.Balancer(claripy.backends.vsa, expr).compat_ret assert s is True assert len(r) == 1 assert r[0][0] is x
def _consolidate_expr(e0): if hasattr(e0, 'op') and e0.op == 'Reverse': e1 = e0.args[0] if e1.op == 'Extract': p0 = e1.args[0] p1 = e1.args[1] e2 = e1.args[2] if e2.op == 'Reverse': return claripy.Extract(e2.size()-1-p1, e2.size()-1-p0, e2.args[0]) return e0
def eq_var(v1, v2): if isinstance(v1, claripy.ast.bv.BV) and isinstance(v2, claripy.ast.bv.BV): v1_size = v1.size() v2_size = v2.size() if v1_size == v2_size: return claripy.ast.Bool(op='__eq__', args=(v1, v2)) elif v1_size in loose_BV_sizes and v2_size in loose_BV_sizes: if v1_size < v2_size: return claripy.And(claripy.ast.Bool(op='__eq__', args=(v1, claripy.Extract(v1_size - 1, 0, v2))), v2[v2_size - 1:v1_size] == 0) else: return claripy.And(claripy.ast.Bool(op='__eq__', args=(claripy.Extract(v2_size - 1, 0, v1), v2)), v1[v1_size - 1:v2_size] == 0) else: return None elif isinstance(v1, claripy.ast.bool.Bool) and isinstance(v2, claripy.ast.bool.Bool): return claripy.ast.Bool(op='__eq__', args=(v1, v2)) else: raise NotImplementedError()
def _op_divmod(self, args): if self.is_signed: quotient = (args[0].SDiv(claripy.SignExt(self._from_size - self._to_size, args[1]))) remainder = (args[0].SMod(claripy.SignExt(self._from_size - self._to_size, args[1]))) quotient_size = self._to_size remainder_size = self._to_size return claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient) ) else: quotient = (args[0] / claripy.ZeroExt(self._from_size - self._to_size, args[1])) remainder = (args[0] % claripy.ZeroExt(self._from_size - self._to_size, args[1])) quotient_size = self._to_size remainder_size = self._to_size return claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient) )
def _handle_DivMod(self, expr): arg0, arg1 = expr.args r0 = self._expr(arg0) r1 = self._expr(arg1) result_size = expr.result_size(self.tyenv) if r0.data.concrete and r1.data.concrete: # constants try: signed = "U" in expr.op # Iop_DivModU64to32 vs Iop_DivMod from_size = r0.data.size() to_size = r1.data.size() if signed: quotient = (r0.data.SDiv( claripy.SignExt(from_size - to_size, r1.data))) remainder = (r0.data.SMod( claripy.SignExt(from_size - to_size, r1.data))) quotient_size = to_size remainder_size = to_size result = claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient)) else: quotient = (r0.data // claripy.ZeroExt(from_size - to_size, r1.data)) remainder = (r0.data % claripy.ZeroExt(from_size - to_size, r1.data)) quotient_size = to_size remainder_size = to_size result = claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient)) return RichR(result) except ZeroDivisionError: pass r = self.state.top(result_size) return RichR(r)
def test_reverse_extract_reverse_simplification(): # without the reverse_extract_reverse simplifier, loading dx from rdx will result in the following complicated # expression: # Reverse(Extract(63, 48, Reverse(BVS('rdx', 64)))) a = claripy.BVS('rdx', 64) dx = claripy.Reverse(claripy.Extract(63, 48, claripy.Reverse(a))) # simplification should have kicked in at this moment nose.tools.assert_equal(dx.op, 'Extract') nose.tools.assert_equal(dx.args[0], 15) nose.tools.assert_equal(dx.args[1], 0) nose.tools.assert_is(dx.args[2], a)
def generic_shift_thing(self, args, op): if self._vector_size is not None: shifted = [] if args[1].length != self._vector_size: shift_by = args[1].zero_extend(self._vector_size - args[1].length) else: shift_by = args[1] for i in reversed(range(self._vector_count)): left = claripy.Extract((i + 1) * self._vector_size - 1, i * self._vector_size, args[0]) shifted.append(op(left, shift_by)) return claripy.Concat(*shifted) else: raise SimOperationError("you done f****d")
def get_signed_range(se, expr): """ Calculate the range of the expression with signed boundaries """ size = expr.size() umin = umax = smin = smax = None if not sat_zero(se, expr): try: umin = se.min(expr, extra_constraints=[ claripy.Extract(size - 1, size - 1, expr) == 0 ]) umax = se.max(expr, extra_constraints=[ claripy.Extract(size - 1, size - 1, expr) == 0 ]) return (umin, umax) except: pass try: smin = -(1 << size) + se.min(expr, extra_constraints=[ claripy.Extract( size - 1, size - 1, expr) == 1 ]) smax = -(1 << size) + se.max(expr, extra_constraints=[ claripy.Extract( size - 1, size - 1, expr) == 1 ]) return (smin, smax) except: pass return None else: try: umax = se.max(expr, extra_constraints=[ claripy.Extract(size - 1, size - 1, expr) == 0 ]) smin = 0 try: smin = -(1 << size) + se.min( expr, extra_constraints=[ claripy.Extract(size - 1, size - 1, expr) == 1 ]) except: pass return (smin, umax) except: pass return None
def _op_vector_float_mapped(self, args): rm_part = [] if self._generic_name in self.NO_RM else [args[0]] chopped_args = ([ claripy.Extract((i + 1) * self._vector_size - 1, i * self._vector_size, a).raw_to_fp() for a in (args if self._generic_name in self.NO_RM else args[1:]) ] for i in reversed(xrange(self._vector_count))) chopped_list = list() for ca in chopped_args: if str(type(self._op_float_mapped( rm_part + ca))) == "<type 'NotImplementedType'>": continue else: chopped_list.add(ca) return claripy.Concat(*(self._op_float_mapped(rm_part + ca).raw_to_bv() for ca in chopped_list))
def test_zeroext_extract_comparing_against_constant_simplifier(): a = claripy.BVS('a', 8, explicit_name=True) b = claripy.BVV(0x28, 16) expr = claripy.Extract(15, 0, claripy.ZeroExt(24, a)) == b assert expr is (a == claripy.BVV(0x28, 8)) expr = claripy.Extract(7, 0, claripy.ZeroExt(24, a)) == claripy.BVV(0x28, 8) assert expr is (a == claripy.BVV(0x28, 8)) expr = claripy.Extract(7, 0, claripy.ZeroExt(1, a)) == claripy.BVV(0x28, 8) assert expr is (a == claripy.BVV(0x28, 8)) expr = claripy.Extract(6, 0, claripy.ZeroExt(24, a)) == claripy.BVV(0x28, 7) assert expr.op == "__eq__" assert expr.args[0].op == "Extract" and expr.args[0].args[ 0] == 6 and expr.args[0].args[1] == 0 assert expr.args[0].args[2] is a assert expr.args[1].args == (0x28, 7) expr = claripy.Extract(15, 0, claripy.Concat(claripy.BVV(0, 48), a)) == b assert expr is (a == claripy.BVV(0x28, 8)) bb = claripy.BVV(0x28, 24) d = claripy.BVS('d', 8, explicit_name=True) expr = claripy.Extract(23, 0, claripy.Concat(claripy.BVV(0, 24), d)) == bb assert expr is (d == claripy.BVV(0x28, 8)) dd = claripy.BVS('dd', 23, explicit_name=True) expr = claripy.Extract(23, 0, claripy.Concat(claripy.BVV(0, 2), dd)) == bb assert expr is (dd == claripy.BVV(0x28, 23)) # this was incorrect before # claripy issue #201 expr = claripy.Extract(31, 8, claripy.Concat(claripy.BVV(0, 24), dd)) == claripy.BVV(0xffff, 24) assert expr is not (dd == claripy.BVV(0xffff, 23))
def _op_vector_float_mapped(self, args): no_rm_arg = self._generic_name in self.NO_RM rm_part = [] if no_rm_arg else [args[0]] # wtf is up with these guys if not no_rm_arg and self.name in { 'Iop_Add32Fx2', 'Iop_Sub32Fx2', 'Iop_Mul32Fx2', 'Iop_PwAdd32Fx2' }: no_rm_arg = True rm_part = [claripy.BVV(0, 8)] chopped_args = ([ claripy.Extract((i + 1) * self._vector_size - 1, i * self._vector_size, a).raw_to_fp() for a in (args if no_rm_arg else args[1:]) ] for i in reversed(range(self._vector_count))) return claripy.Concat(*(self._op_float_mapped(rm_part + ca).raw_to_bv() for ca in chopped_args))
def _handle_Shr(self, expr): args, r = self._binop_get_args(expr) if args is None: return r expr_0, expr_1 = args if self._is_top(expr_0) or self._is_top(expr_1): return self._top(expr_0.size()) if isinstance(expr_1, claripy.ast.Base) and expr_1.op == "BVV": # convert it to an int when possible expr_1 = expr_1.args[0] else: # make sure the sizes are the same - VEX does not care about it if expr_1.size() < expr_0.size(): expr_1 = claripy.ZeroExt(expr_0.size() - expr_1.size(), expr_1) elif expr_1.size() > expr_0.size(): expr_1 = claripy.Extract(expr_0.size() - 1, 0, expr_1) return claripy.LShR(expr_0, expr_1)
def _post_process(self): if self._post_processed: return self._post_processed = True if o.SIMPLIFY_EXPRS in self.state.options: self.expr = self.state.se.simplify(self.expr) self.state.add_constraints(*self._constraints) if self.state.se.symbolic( self.expr) and o.CONCRETIZE in self.state.options: self.make_concrete() # FIXME: add this will cause BV96 data, why? if self.expr.size() != self.size_bits(): l.warning("Inconsistent expression size: should be %d but is %d" % (self.size_bits(), self.expr.size())) if self.expr.size() > self.size_bits(): self.expr = claripy.Extract(self.size_bits() - 1, 0, self.expr) else: self.expr = claripy.ZeroExt( self.size_bits() - self.expr.size(), self.expr)
def _op_fgeneric_Round(self, args): if self._vector_size is not None: rm = { 'RM': claripy.fp.RM_RTN, 'RP': claripy.fp.RM_RTP, 'RN': claripy.fp.RM_RNE, 'RZ': claripy.fp.RM_RTZ, }[self._rounding_mode] rounded = [] for i in reversed(range(self._vector_count)): #pylint:disable=no-member left = claripy.Extract( (i+1) * self._vector_size - 1, i * self._vector_size, args[0] ).raw_to_fp() rounded.append(claripy.fpToSBV(rm, left, self._vector_size)) return claripy.Concat(*rounded) else: # note: this a bad solution because it will cut off high values # TODO: look into fixing this rm = self._translate_rm(args[0]) rounded_bv = claripy.fpToSBV(rm, args[1].raw_to_fp(), args[1].length) return claripy.fpToFP(claripy.fp.RM_RNE, rounded_bv, claripy.fp.FSort.from_size(args[1].length))
def evaluate_unary(self, size_out: int, size_in: int, in1: BV) -> BV: expr = claripy.BVV(0, size_out * 8) for a in range(len(in1)): expr += claripy.Extract(a, a, in1).zero_extend(size_out * 8 - 1) return expr
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_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) ) )
def sat_negative(se, expr): size = expr.size() return se.satisfiable( extra_constraints=([claripy.Extract(size - 1, size - 1, expr) == 1]))
def sat_positive(se, expr): return se.satisfiable( extra_constraints=([claripy.Extract(size - 1, size - 1, expr) == 0]))
def _op_generic_GetMSBs(self, args): size = self._vector_count * self._vector_size bits = [claripy.Extract(i, i, args[0]) for i in range(size - 1, 6, -8)] return claripy.Concat(*bits)
def _op_extract(self, args): return claripy.Extract(self._to_size - 1, 0, args[0])
def _op_lo_half(self, args): return claripy.Extract(args[0].size() // 2 - 1, 0, args[0])
def _op_hi_half(self, args): return claripy.Extract(args[0].size() - 1, args[0].size() // 2, args[0])
def _op_vector_mapped(self, args): chopped_args = ([ claripy.Extract((i + 1) * self._vector_size - 1, i * self._vector_size, a) for a in args ] for i in reversed(range(self._vector_count))) return claripy.Concat(*(self._op_mapped(ca) for ca in chopped_args))
def _ail_handle_Convert(self, expr: Expr.Convert) -> PropValue: o_value = self._expr(expr.operand) if o_value is None or self.state.is_top(o_value.value): new_value = self.state.top(expr.to_bits) else: if expr.from_bits < expr.to_bits: if expr.is_signed: new_value = claripy.SignExt(expr.to_bits - expr.from_bits, o_value.value) else: new_value = claripy.ZeroExt(expr.to_bits - expr.from_bits, o_value.value) elif expr.from_bits > expr.to_bits: new_value = claripy.Extract(expr.to_bits - 1, 0, o_value.value) else: new_value = o_value.value o_expr = o_value.one_expr o_defat = o_value.one_defat if o_expr is not None: # easy cases if type(o_expr) is Expr.Convert: if expr.from_bits == o_expr.to_bits and expr.to_bits == o_expr.from_bits: # eliminate the redundant Convert new_expr = o_expr.operand else: new_expr = Expr.Convert(expr.idx, o_expr.from_bits, expr.to_bits, expr.is_signed, o_expr.operand) elif type(o_expr) is Expr.Const: # do the conversion right away value = o_expr.value mask = (2 ** expr.to_bits) - 1 value &= mask new_expr = Expr.Const(expr.idx, o_expr.variable, value, expr.to_bits) else: new_expr = Expr.Convert(expr.idx, expr.from_bits, expr.to_bits, expr.is_signed, o_expr, **expr.tags) if isinstance(new_expr, Expr.Convert) and not new_expr.is_signed \ and new_expr.to_bits > new_expr.from_bits and new_expr.from_bits % self.arch.byte_width == 0: # special handling for zero-extension: it simplifies the code if we explicitly model zeros new_size = new_expr.from_bits // self.arch.byte_width offset_and_details = { 0: Detail(new_size, new_expr.operand, o_defat), new_size: Detail( new_expr.size - new_size, Expr.Const(expr.idx, None, 0, new_expr.to_bits - new_expr.from_bits), self._codeloc()), } else: offset_and_details = {0: Detail(expr.size, new_expr, self._codeloc())} return PropValue(new_value, offset_and_details=offset_and_details) elif o_value.offset_and_details: # hard cases... we will keep certain labels and eliminate other labels start_offset = 0 end_offset = expr.to_bits // self.arch.byte_width # end_offset is exclusive offset_and_details = {} max_offset = max(o_value.offset_and_details.keys()) for offset_, detail_ in o_value.offset_and_details.items(): if offset_ < start_offset < offset_ + detail_.size: # we start here off = 0 siz = min(end_offset, offset_ + detail_.size) - start_offset expr_ = PropValue.extract_ail_expression( (start_offset - offset_) * self.arch.byte_width, siz * self.arch.byte_width, detail_.expr ) offset_and_details[off] = Detail(siz, expr_, detail_.def_at) elif offset_ >= start_offset and offset_ + detail_.size <= end_offset: # we include the whole thing off = offset_ - start_offset siz = detail_.size if off == max_offset and off + siz < end_offset: # extend the expr expr_ = PropValue.extend_ail_expression( (end_offset - (off + siz)) * self.arch.byte_width, detail_.expr ) siz = end_offset - off else: expr_ = detail_.expr offset_and_details[off] = Detail(siz, expr_, detail_.def_at) elif offset_ < end_offset <= offset_ + detail_.size: # we include all the way until end_offset if offset_ < start_offset: off = 0 siz = end_offset - start_offset else: off = offset_ - start_offset siz = end_offset - offset_ expr_ = PropValue.extract_ail_expression(0, siz * self.arch.byte_width, detail_.expr) offset_and_details[off] = Detail(siz, expr_, detail_.def_at) return PropValue( new_value, offset_and_details=offset_and_details ) else: # it's empty... no expression is available for whatever reason return PropValue.from_value_and_details(new_value, expr.size, expr, self._codeloc())
def extend_BV32_to_BV64(f, bvs_dict): is_bv = isinstance(f, claripy.ast.bv.BV) is_bool = isinstance(f, claripy.ast.bool.Bool) if not is_bv and not is_bool: return f if f.depth == 1: if isinstance(f, claripy.ast.bv.BV) and f.size() == 32: if f.symbolic: f_name = str(f._encoded_name, 'utf8') f_name = f_name[:f_name.rfind('_')] f_name = f_name[:f_name.rfind('_')] if f_name not in bvs_dict: bvs_dict[f_name] = claripy.BVS(name=f_name, size=64) return bvs_dict[f_name] else: if f.args[0] & (1 << 31): return claripy.BVV(0xffffffff00000000 | f.args[0], 64) else: return claripy.BVV(f.args[0], 64) else: return f elif f.depth == 2 and f.op == 'Extract' and f.args[ 2].symbolic and f.args[2].size() == 32: # an Extract is regarded as a leaf node return claripy.Extract( f.args[0], f.args[1], FormulaExtractor.extend_BV32_to_BV64(f.args[2], bvs_dict)) elif f.op == 'Concat': # we make sure that Concat will not change the size of f new_args = [] for arg in f.args: tmp = FormulaExtractor.extend_BV32_to_BV64(arg, bvs_dict) # we Extract the corresponding bits tmp = claripy.Extract(arg.size() - 1, 0, tmp) new_args.append(tmp) return claripy.Concat(*new_args) elif hasattr(f, 'args') and hasattr(f, 'size'): # many binary op requires same size of left hand side and right hand side # if LHS and RHS are 32 bits, we turn both side into 64 bits new_args = [] all_same_size = True for i in range(len(f.args) - 1): if not hasattr(f.args[i], 'size') or not hasattr(f.args[i + 1], 'size') \ or f.args[i].size() != f.args[i + 1].size(): all_same_size = False break if f.op.startswith('__') and all_same_size: new_args = [ FormulaExtractor.extend_BV32_to_BV64( f.args[idx], bvs_dict) for idx in range(len(f.args)) ] # we simply think LHS and RHS mush have same size if f.args[0].size() == 32: # we extend the size to 64 bits for idx in range(len(f.args)): if new_args[idx].size() < 64: new_args[idx] = claripy.Concat( claripy.BVV(0, 64 - new_args[idx].size()), new_args[idx]) else: # we make sure the size has not been changed for idx in range(len(f.args)): if new_args[idx].size() > f.args[idx].size(): new_args[idx] = claripy.Extract( f.args[idx].size() - 1, 0, new_args[idx]) elif new_args[idx].size() < f.args[idx].size(): new_args[idx] = claripy.Concat( claripy.BVV( 0, f.args[idx].size() - new_args[idx].size()), new_args[idx]) else: for arg in f.args: new_args.append( FormulaExtractor.extend_BV32_to_BV64(arg, bvs_dict)) if is_bv: f = claripy.ast.BV(op=f.op, args=tuple(new_args), length=64) elif is_bool: f = claripy.ast.Bool(op=f.op, args=tuple(new_args)) return f else: new_args = [] for arg in f.args: new_args.append( FormulaExtractor.extend_BV32_to_BV64(arg, bvs_dict)) if is_bv: f = claripy.ast.BV(op=f.op, args=tuple(new_args), length=64) elif is_bool: f = claripy.ast.Bool(op=f.op, args=tuple(new_args)) return f