def Sum(*args: BitVec) -> BitVec: """Create sum expression. :return: """ raw = z3.Sum([a.raw for a in args]) annotations = [] # type: Annotations bitvecfuncs = [] for bv in args: annotations += bv.annotations if isinstance(bv, BitVecFunc): bitvecfuncs.append(bv) if len(bitvecfuncs) >= 2: return BitVecFunc(raw=raw, func_name=None, input_=None, annotations=annotations) elif len(bitvecfuncs) == 1: return BitVecFunc( raw=raw, func_name=bitvecfuncs[0].func_name, input_=bitvecfuncs[0].input_, annotations=annotations, ) return BitVec(raw, annotations)
def Concat(*args: Union[BitVec, List[BitVec]]) -> BitVec: """Create a concatenation expression. :param args: :return: """ # The following statement is used if a list is provided as an argument to concat if len(args) == 1 and isinstance(args[0], list): bvs = args[0] # type: List[BitVec] else: bvs = cast(List[BitVec], args) nraw = z3.Concat([a.raw for a in bvs]) annotations = [] # type: Annotations bitvecfunc = False for bv in bvs: annotations += bv.annotations if isinstance(bv, BitVecFunc): bitvecfunc = True if bitvecfunc: # Is there a better value to set func_name and input to in this case? return BitVecFunc(raw=nraw, func_name=None, input_=None, annotations=annotations) return BitVec(nraw, annotations)
def Concat(*args: Union[BitVec, List[BitVec]]) -> BitVec: """Create a concatenation expression. :param args: :return: """ # The following statement is used if a list is provided as an argument to concat if len(args) == 1 and isinstance(args[0], list): bvs = args[0] # type: List[BitVec] else: bvs = cast(List[BitVec], args) nraw = z3.Concat([a.raw for a in bvs]) annotations = set() # type: Annotations nested_functions = [] # type: List[BitVecFunc] for bv in bvs: annotations = annotations.union(bv.annotations) if isinstance(bv, BitVecFunc): nested_functions += bv.nested_functions nested_functions += [bv] if nested_functions: return BitVecFunc( raw=nraw, func_name="Hybrid", input_=BitVec(z3.BitVec("", 256), annotations=annotations), nested_functions=nested_functions, ) return BitVec(nraw, annotations)
def Concat(*args: Union[BitVec, List[BitVec]]) -> BitVec: """Create a concatenation expression. :param args: :return: """ # The following statement is used if a list is provided as an argument to concat if len(args) == 1 and isinstance(args[0], list): bvs = args[0] # type: List[BitVec] else: bvs = cast(List[BitVec], args) nraw = z3.Concat([a.raw for a in bvs]) annotations = set() # type: Annotations bitvecfunc = False for bv in bvs: annotations = annotations.union(bv.annotations) if isinstance(bv, BitVecFunc): bitvecfunc = True if bitvecfunc: # Added this not so good and misleading NOTATION to help with this str_hash = ",".join(["hashed({})".format(hash(bv)) for bv in bvs]) input_string = "MisleadingNotationConcat({})".format(str_hash) return BitVecFunc(raw=nraw, func_name="Hybrid", input_=BitVec(z3.BitVec(input_string, 256), annotations=annotations)) return BitVec(nraw, annotations)
def BitVecFuncSym( name: str, func_name: str, size: int, annotations: Annotations = None, input_: Union[int, "BitVec"] = None, ) -> BitVecFunc: """Creates a new bit vector function with a symbolic value.""" raw = z3.BitVec(name, size) return BitVecFunc(raw, func_name, input_, annotations)
def BitVecFuncVal( value: int, func_name: str, size: int, annotations: Annotations = None, input_: Union[int, "BitVec"] = None, ) -> BitVecFunc: """Creates a new bit vector function with a concrete value.""" raw = z3.BitVecVal(value, size) return BitVecFunc(raw, func_name, input_, annotations)
def _arithmetic_helper(a: BitVec, b: BitVec, operation: Callable) -> BitVec: raw = operation(a.raw, b.raw) union = a.annotations + b.annotations if isinstance(a, BitVecFunc) and isinstance(b, BitVecFunc): return BitVecFunc(raw=raw, func_name=None, input_=None, annotations=union) elif isinstance(a, BitVecFunc): return BitVecFunc(raw=raw, func_name=a.func_name, input_=a.input_, annotations=union) elif isinstance(b, BitVecFunc): return BitVecFunc(raw=raw, func_name=b.func_name, input_=b.input_, annotations=union) return BitVec(raw, annotations=union)
def Sum(*args: BitVec) -> BitVec: """Create sum expression. :return: """ raw = z3.Sum([a.raw for a in args]) annotations = set() # type: Annotations bitvecfuncs = [] for bv in args: annotations = annotations.union(bv.annotations) if isinstance(bv, BitVecFunc): bitvecfuncs.append(bv) nested_functions = [ nf for func in bitvecfuncs for nf in func.nested_functions ] + bitvecfuncs if len(bitvecfuncs) >= 2: return BitVecFunc( raw=raw, func_name="Hybrid", input_=None, annotations=annotations, nested_functions=nested_functions, ) elif len(bitvecfuncs) == 1: return BitVecFunc( raw=raw, func_name=bitvecfuncs[0].func_name, input_=bitvecfuncs[0].input_, annotations=annotations, nested_functions=nested_functions, ) return BitVec(raw, annotations)
def Extract(high: int, low: int, bv: BitVec) -> BitVec: """Create an extract expression. :param high: :param low: :param bv: :return: """ raw = z3.Extract(high, low, bv.raw) if isinstance(bv, BitVecFunc): # Is there a better value to set func_name and input to in this case? return BitVecFunc(raw=raw, func_name=None, input_=None, annotations=bv.annotations) return BitVec(raw, annotations=bv.annotations)
def Extract(high: int, low: int, bv: BitVec) -> BitVec: """Create an extract expression. :param high: :param low: :param bv: :return: """ raw = z3.Extract(high, low, bv.raw) if isinstance(bv, BitVecFunc): input_string = "MisleadingNotationExtract({}, {}, hashed({}))".format( high, low, hash(bv)) # Is there a better value to set func_name and input to in this case? return BitVecFunc(raw=raw, func_name="Hybrid", input_=BitVec(z3.BitVec(input_string, 256), annotations=bv.annotations)) return BitVec(raw, annotations=bv.annotations)
def Extract(high: int, low: int, bv: BitVec) -> BitVec: """Create an extract expression. :param high: :param low: :param bv: :return: """ raw = z3.Extract(high, low, bv.raw) if isinstance(bv, BitVecFunc): input_string = "" # Is there a better value to set func_name and input to in this case? return BitVecFunc( raw=raw, func_name="Hybrid", input_=BitVec(z3.BitVec(input_string, 256), annotations=bv.annotations), nested_functions=bv.nested_functions + [bv], ) return BitVec(raw, annotations=bv.annotations)
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)