def __ne__(self, other: Union[int, "BitVec"]) -> Bool: # type: ignore """Create an inequality expression. :param other: :return: """ if not isinstance(other, BitVec): return Bool(cast(z3.BoolRef, self.raw != other), annotations=self.annotations) union = self.annotations + other.annotations # MYPY: fix complaints due to z3 overriding __eq__ return Bool(cast(z3.BoolRef, self.raw != other.raw), annotations=union)
def _comparison_helper(a: BitVec, b: BitVec, operation: Callable, default_value: bool, inputs_equal: bool) -> Bool: annotations = a.annotations.union(b.annotations) if isinstance(a, BitVecFunc): return _func_comparison_helper(a, b, operation, default_value, inputs_equal) return Bool(operation(a.raw, b.raw), annotations)
def _comparison_helper(a: BitVec, b: BitVec, operation: Callable, default_value: bool, inputs_equal: bool) -> Bool: annotations = a.annotations + b.annotations if isinstance(a, BitVecFunc): if not a.symbolic and not b.symbolic: return Bool(operation(a.raw, b.raw), annotations=annotations) if (not isinstance(b, BitVecFunc) or not a.func_name or not a.input_ or not a.func_name == b.func_name): return Bool(z3.BoolVal(default_value), annotations=annotations) return And( Bool(operation(a.raw, b.raw), annotations=annotations), a.input_ == b.input_ if inputs_equal else a.input_ != b.input_, ) return Bool(operation(a.raw, b.raw), annotations)
def __ge__(self, other: "BitVec") -> Bool: """Create a signed greater than expression. :param other: :return: """ union = self.annotations + other.annotations return Bool(self.raw >= other.raw, annotations=union)
def __ne__(self, other: Union[int, "BitVec"]) -> Bool: # type: ignore """Create an inequality expression. :param other: :return: """ if isinstance(other, BitVecFunc): return other != self if not isinstance(other, BitVec): return Bool(cast(z3.BoolRef, self.raw != other), annotations=self.annotations) union = self.annotations.union(other.annotations) # Some of the BitVecs can be 512 bit due to sha3() neq_check = _padded_operation(self.raw, other.raw, ne) # MYPY: fix complaints due to z3 overriding __eq__ return Bool(cast(z3.BoolRef, neq_check), annotations=union)
def __le__(self, other: "BitVec") -> Bool: """Create a signed less than expression. :param other: :return: """ union = self.annotations.union(other.annotations) return Bool(self.raw <= other.raw, annotations=union)
def ULT(a: BitVec, b: BitVec) -> Bool: """Create an unsigned less than expression. :param a: :param b: :return: """ annotations = a.annotations + b.annotations return Bool(z3.ULT(a.raw, b.raw), annotations)
def UGE(a: BitVec, b: BitVec) -> Bool: """Create an unsigned greater or equals expression. :param a: :param b: :return: """ annotations = a.annotations + b.annotations return Bool(z3.UGE(a.raw, b.raw), annotations)
def Bool(value: "__builtins__.bool", annotations: Annotations = None) -> bool.Bool: """ Creates a Bool with concrete value :param value: The boolean value :param annotations: The annotations to initialize the bool with :return: The freshly created Bool() """ raw = z3.BoolVal(value) return Bool(raw, annotations)
def __gt__(self, other: "BitVec") -> Bool: """Create a signed greater than expression. :param other: :return: """ if isinstance(other, BitVecFunc): return other < self union = self.annotations + other.annotations return Bool(self.raw > other.raw, annotations=union)
def __ge__(self, other: Union[int, "BitVec"]) -> Bool: """Create a signed greater than expression. :param other: :return: """ if not isinstance(other, BitVec): other = BitVec(z3.BitVecVal(other, self.size())) union = self.annotations.union(other.annotations) return Bool(self.raw >= other.raw, annotations=union)
def __lt__(self, other: "BitVec") -> Bool: """Create a signed less than expression. :param other: :return: """ if isinstance(other, BitVecFunc): return other > self union = self.annotations.union(other.annotations) return Bool(self.raw < other.raw, annotations=union)
def BVAddNoOverflow(a: Union[BitVec, int], b: Union[BitVec, int], signed: bool) -> Bool: """Creates predicate that verifies that the addition doesn't overflow. :param a: :param b: :param signed: :return: """ if not isinstance(a, BitVec): a = BitVec(z3.BitVecVal(a, 256)) if not isinstance(b, BitVec): b = BitVec(z3.BitVecVal(b, 256)) return Bool(z3.BVAddNoOverflow(a.raw, b.raw, signed))
def If(a: Union[Bool, bool], b: Union[BitVec, int], c: Union[BitVec, int]) -> BitVec: """Create an if-then-else expression. :param a: :param b: :param c: :return: """ if not isinstance(a, Bool): a = Bool(z3.BoolVal(a)) if not isinstance(b, BitVec): b = BitVec(z3.BitVecVal(b, 256)) if not isinstance(c, BitVec): c = BitVec(z3.BitVecVal(c, 256)) union = a.annotations + b.annotations + c.annotations return BitVec(z3.If(a.raw, b.raw, c.raw), union)
def If(a: Union[Bool, bool], b: Union[BitVec, int], c: Union[BitVec, int]) -> BitVec: """Create an if-then-else expression. :param a: :param b: :param c: :return: """ # TODO: Handle BitVecFunc if not isinstance(a, Bool): a = Bool(z3.BoolVal(a)) if not isinstance(b, BitVec): b = BitVec(z3.BitVecVal(b, 256)) if not isinstance(c, BitVec): c = BitVec(z3.BitVecVal(c, 256)) union = a.annotations.union(b.annotations).union(c.annotations) bvf = [] # type: List[BitVecFunc] if isinstance(a, BitVecFunc): bvf += [a] if isinstance(b, BitVecFunc): bvf += [b] if isinstance(c, BitVecFunc): bvf += [c] if bvf: raw = z3.If(a.raw, b.raw, c.raw) nested_functions = [ nf for func in bvf for nf in func.nested_functions ] + bvf return BitVecFunc(raw, func_name="Hybrid", nested_functions=nested_functions) return BitVec(z3.If(a.raw, b.raw, c.raw), union)
def _comparison_helper( a: "BitVecFunc", b: Union[BitVec, int], operation: Callable, default_value: bool, inputs_equal: bool, ) -> Bool: """ Helper function for comparison operations with BitVecFuncs. :param a: The BitVecFunc to compare. :param b: A BitVec or int to compare to. :param operation: The comparison operation to perform. :return: The resulting Bool """ # Is there some hack for gt/lt comparisons? if isinstance(b, int): b = BitVec(z3.BitVecVal(b, a.size())) union = a.annotations.union(b.annotations) if not a.symbolic and not b.symbolic: if operation == z3.UGT: operation = operator.gt if operation == z3.ULT: operation = operator.lt return Bool(z3.BoolVal(operation(a.value, b.value)), annotations=union) if ( not isinstance(b, BitVecFunc) or not a.func_name or not a.input_ or not a.func_name == b.func_name or str(operation) not in ("<built-in function eq>", "<built-in function ne>") ): return Bool(z3.BoolVal(default_value), annotations=union) condition = True for a_nest, b_nest in product(a.nested_functions, b.nested_functions): if a_nest.func_name != b_nest.func_name: continue if a_nest.func_name == "Hybrid": continue # a.input (eq/neq) b.input ==> a == b if inputs_equal: condition = z3.And( condition, z3.Or( z3.Not((a_nest.input_ == b_nest.input_).raw), (a_nest.raw == b_nest.raw), ), z3.Or( z3.Not((a_nest.raw == b_nest.raw)), (a_nest.input_ == b_nest.input_).raw, ), ) else: condition = z3.And( condition, z3.Or( z3.Not((a_nest.input_ != b_nest.input_).raw), (a_nest.raw == b_nest.raw), ), z3.Or( z3.Not((a_nest.raw == b_nest.raw)), (a_nest.input_ != b_nest.input_).raw, ), ) return And( Bool(cast(z3.BoolRef, operation(a.raw, b.raw)), annotations=union), Bool(condition) if b.nested_functions else Bool(True), a.input_ == b.input_ if inputs_equal else a.input_ != b.input_, )