diff options
| author | Peter LaFosse <peter@vector35.com> | 2022-01-18 09:48:47 -0500 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2022-01-19 10:53:46 -0500 |
| commit | 6f5fd10c589cd7bf525d91a60a0dc66bc4f93e25 (patch) | |
| tree | cb5d1f10dbc65bd5bd96e5b7eb6551190f8783d7 | |
| parent | 12b55e3265ea0538b911be910b8300af807c4695 (diff) | |
Many type check fixes
| -rw-r--r-- | python/architecture.py | 36 | ||||
| -rw-r--r-- | python/basicblock.py | 148 | ||||
| -rw-r--r-- | python/binaryview.py | 46 | ||||
| -rw-r--r-- | python/databuffer.py | 11 | ||||
| -rw-r--r-- | python/demangle.py | 2 | ||||
| -rw-r--r-- | python/filemetadata.py | 2 | ||||
| -rw-r--r-- | python/function.py | 221 | ||||
| -rw-r--r-- | python/highlevelil.py | 30 | ||||
| -rw-r--r-- | python/lineardisassembly.py | 67 | ||||
| -rw-r--r-- | python/log.py | 2 | ||||
| -rw-r--r-- | python/lowlevelil.py | 123 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 120 | ||||
| -rw-r--r-- | python/platform.py | 18 | ||||
| -rw-r--r-- | python/types.py | 26 | ||||
| -rw-r--r-- | python/variable.py | 15 |
15 files changed, 362 insertions, 505 deletions
diff --git a/python/architecture.py b/python/architecture.py index 3201615b..fd9e28f1 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -509,10 +509,10 @@ class Architecture(metaclass=_ArchitectureMetaClass): count = ctypes.c_ulonglong() regs = core.BNGetFullWidthArchitectureRegisters(self.handle, count) assert regs is not None, "core.BNGetFullWidthArchitectureRegisters returned None" - result = [] + result:List[RegisterName] = [] try: for i in range(0, count.value): - result.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) + result.append(RegisterName(core.BNGetArchitectureRegisterName(self.handle, regs[i]))) finally: core.BNFreeRegisterList(regs) return result @@ -529,7 +529,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): obj = callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i])) result[obj.name] = obj finally: - core.BNFreeCallingConventionList(cc, count) + core.BNFreeCallingConventionList(cc, count.value) return result @property @@ -1173,10 +1173,10 @@ class Architecture(metaclass=_ArchitectureMetaClass): buf = ctypes.cast(buf_raw, ctypes.c_void_p) if buf.value not in self._pending_type_lists: raise ValueError("freeing type list that wasn't allocated") - types = self._pending_type_lists[buf.value][1] + _types = self._pending_type_lists[buf.value][1] count = self._pending_type_lists[buf.value][2] for i in range(0, count): - core.BNFreeType(types[i].type) + core.BNFreeType(_types[i].type) del self._pending_type_lists[buf.value] except (ValueError, KeyError): log_error(traceback.format_exc()) @@ -1425,7 +1425,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): result = core.BNGetArchitectureRegisterStackForRegister(self.handle, _reg) if result == 0xffffffff: return None - return self.get_reg_stack_name(result) + return self.get_reg_stack_name(RegisterStackIndex(result)) def get_flag_name(self, flag:FlagIndex) -> FlagName: """ @@ -1465,7 +1465,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): def get_flag_index(self, flag:FlagType) -> FlagIndex: if isinstance(flag, str): - return self._flags[flag] + return self._flags[FlagName(flag)] elif isinstance(flag, lowlevelil.ILFlag): return flag.index elif isinstance(flag, int): @@ -1487,7 +1487,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): """ ``get_semantic_flag_class_name`` gets the name of a semantic flag class from the index. - :param int _index: class_index + :param int class_index: class_index :return: the name of the semantic flag class :rtype: str """ @@ -1497,7 +1497,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): def get_semantic_flag_group_index(self, sem_group:SemanticGroupType) -> SemanticGroupIndex: if isinstance(sem_group, str): - return self._semantic_flag_groups[sem_group] + return self._semantic_flag_groups[SemanticGroupName(sem_group)] elif isinstance(sem_group, lowlevelil.ILSemanticFlagGroup): return sem_group.index return sem_group @@ -1609,6 +1609,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): :param LowLevelILOperation op: :param int size: :param str write_type: + :param FlagType flag: :param operands: a list of either items that are either string register names or constant integer values :type operands: list(str) or list(int) :param LowLevelILFunction il: @@ -1695,9 +1696,9 @@ class Architecture(metaclass=_ArchitectureMetaClass): count = ctypes.c_ulonglong() regs = core.BNGetModifiedArchitectureRegistersOnWrite(self.handle, reg, count) assert regs is not None, "core.BNGetModifiedArchitectureRegistersOnWrite is not None" - result = [] + result:List[RegisterName] = [] for i in range(0, count.value): - result.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) + result.append(RegisterName(core.BNGetArchitectureRegisterName(self.handle, regs[i]))) core.BNFreeRegisterList(regs) return result @@ -1865,10 +1866,10 @@ class Architecture(metaclass=_ArchitectureMetaClass): :rtype: str :Example: - >>> bytes = arch.always_branch(arch.assemble("je 10"), 0) - >>> arch.get_instruction_text(bytes, 0) + >>> data = arch.always_branch(arch.assemble("je 10"), 0) + >>> arch.get_instruction_text(data, 0) (['nop', ' '], 1) - >>> arch.get_instruction_text(bytes[1:], 0) + >>> arch.get_instruction_text(data[1:], 0) (['jmp', ' ', '0x9'], 5) >>> """ @@ -1940,7 +1941,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): :param str type_name: the BinaryView type name of the constant to be retrieved :param str const_name: the constant name to retrieved - :param int value: optional default value if the type_name is not present. default value is zero. + :param int default_value: optional default value if the type_name is not present. default value is zero. :return: The BinaryView type constant or the default_value if not found :rtype: int :Example: @@ -2527,8 +2528,8 @@ class CoreArchitecture(Architecture): :rtype: str :Example: - >>> bytes = arch.always_branch(arch.assemble("je 10"), 0) - >>> arch.get_instruction_text(bytes, 0) + >>> data = arch.always_branch(arch.assemble("je 10"), 0) + >>> arch.get_instruction_text(data, 0) (['nop', ' '], 1) >>> arch.get_instruction_text(bytes[1:], 0) (['jmp', ' ', '0x9'], 5) @@ -2576,6 +2577,7 @@ class CoreArchitecture(Architecture): :param str data: bytes for the instruction to be converted :param int addr: the virtual address of the instruction to be patched + :param int value: the value to return :return: string containing len(data) which always branches to the same location as the provided instruction :rtype: str :Example: diff --git a/python/basicblock.py b/python/basicblock.py index 0fa16d12..c73fd604 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -130,7 +130,7 @@ class BasicBlock: return self.arch.get_instruction_text(data, start) def __contains__(self, i:int): - return i >= self.start and i < self.end + return self.start <= i < self.end def _buildStartCache(self) -> None: if self._instStarts is None: @@ -220,46 +220,39 @@ class BasicBlock: """Basic block index in list of blocks for the function (read-only)""" return core.BNGetBasicBlockIndex(self.handle) - @property - def outgoing_edges(self) -> List[BasicBlockEdge]: - """List of basic block outgoing edges (read-only)""" - if self.view is None: - raise Exception("Attempting to call BasicBlock.outgoing_edges when BinaryView is None") - count = ctypes.c_ulonglong(0) - edges = core.BNGetBasicBlockOutgoingEdges(self.handle, count) - assert edges is not None, "core.BNGetBasicBlockOutgoingEdges returned None" - result = [] + + def _make_edges(self, edges, count:int, direction:bool) -> List[BasicBlockEdge]: + assert edges is not None, "Got empty edges list from core" + assert self.view is not None, "Attempting to get BasicBlock edges when BinaryView is None" + result:List[BasicBlockEdge] = [] try: - for i in range(0, count.value): + for i in range(0, count): branch_type = BranchType(edges[i].type) handle = core.BNNewBasicBlockReference(edges[i].target) assert handle is not None target = self._create_instance(handle, self.view) - result.append(BasicBlockEdge(branch_type, self, target, edges[i].backEdge, edges[i].fallThrough)) + if direction: + sink, source = target, self + else: + sink, source = self, target + result.append(BasicBlockEdge(branch_type, sink, source, edges[i].backEdge, edges[i].fallThrough)) return result finally: - core.BNFreeBasicBlockEdgeList(edges, count.value) + core.BNFreeBasicBlockEdgeList(edges, count) + + + @property + def outgoing_edges(self) -> List[BasicBlockEdge]: + """List of basic block outgoing edges (read-only)""" + count = ctypes.c_ulonglong(0) + return self._make_edges(core.BNGetBasicBlockOutgoingEdges(self.handle, count), count.value, False) @property def incoming_edges(self) -> List[BasicBlockEdge]: """List of basic block incoming edges (read-only)""" count = ctypes.c_ulonglong(0) - if self.view is None: - raise Exception("Attempting to buildStartCache when BinaryView for BasicBlock is None") + return self._make_edges(core.BNGetBasicBlockIncomingEdges(self.handle, count), count.value, True) - edges = core.BNGetBasicBlockIncomingEdges(self.handle, count) - assert edges is not None, "core.BNGetBasicBlockIncomingEdges returned None" - result = [] - try: - for i in range(0, count.value): - branch_type = BranchType(edges[i].type) - handle = core.BNNewBasicBlockReference(edges[i].target) - assert handle is not None - target = self._create_instance(handle, self.view) - result.append(BasicBlockEdge(branch_type, target, self, edges[i].backEdge, edges[i].fallThrough)) - return result - finally: - core.BNFreeBasicBlockEdgeList(edges, count.value) @property def has_undetermined_outgoing_edges(self) -> bool: @@ -281,23 +274,26 @@ class BasicBlock: """Whether basic block has any invalid instructions (read-only)""" return core.BNBasicBlockHasInvalidInstructions(self.handle) - @property - def dominators(self) -> List['BasicBlock']: - """List of dominators for this basic block (read-only)""" - if self.view is None: - raise Exception("Attempting to call BasicBlock.dominators when BinaryView is None") - count = ctypes.c_ulonglong() - blocks = core.BNGetBasicBlockDominators(self.handle, count, False) - assert blocks is not None, "core.BNGetBasicBlockDominators returned None" - result = [] + def _make_blocks(self, blocks, count:int) -> List['BasicBlock']: + assert blocks is not None, "core returned empty block list" + result:List['BasicBlock'] = [] try: - for i in range(0, count.value): + for i in range(0, count): handle = core.BNNewBasicBlockReference(blocks[i]) assert handle is not None result.append(self._create_instance(handle, self.view)) return result finally: - core.BNFreeBasicBlockList(blocks, count.value) + core.BNFreeBasicBlockList(blocks, count) + + @property + def dominators(self) -> List['BasicBlock']: + """List of dominators for this basic block (read-only)""" + if self.view is None: + raise Exception("Attempting to call BasicBlock.dominators when BinaryView is None") + count = ctypes.c_ulonglong() + return self._make_blocks(core.BNGetBasicBlockDominators(self.handle, count, False), count.value) + @property def post_dominators(self) -> List['BasicBlock']: @@ -305,17 +301,7 @@ class BasicBlock: if self.view is None: raise Exception("Attempting to call BasicBlock.post_dominators when BinaryView is None") count = ctypes.c_ulonglong() - blocks = core.BNGetBasicBlockDominators(self.handle, count, True) - assert blocks is not None, "core.BNGetBasicBlockDominators returned None" - result = [] - try: - for i in range(0, count.value): - handle = core.BNNewBasicBlockReference(blocks[i]) - assert handle is not None, "core.BNNewBasicBlockReference returned None" - result.append(self._create_instance(handle, self.view)) - return result - finally: - core.BNFreeBasicBlockList(blocks, count.value) + return self._make_blocks(core.BNGetBasicBlockDominators(self.handle, count, True), count.value) @property def strict_dominators(self) -> List['BasicBlock']: @@ -323,17 +309,7 @@ class BasicBlock: if self.view is None: raise Exception("Attempting to call BasicBlock.strict_dominators when BinaryView is None") count = ctypes.c_ulonglong() - blocks = core.BNGetBasicBlockStrictDominators(self.handle, count, False) - assert blocks is not None, "core.BNGetBasicBlockStrictDominators returned None" - result = [] - try: - for i in range(0, count.value): - handle = core.BNNewBasicBlockReference(blocks[i]) - assert handle is not None - result.append(self._create_instance(handle, self.view)) - return result - finally: - core.BNFreeBasicBlockList(blocks, count.value) + return self._make_blocks(core.BNGetBasicBlockStrictDominators(self.handle, count, False), count.value) @property def immediate_dominator(self) -> Optional['BasicBlock']: @@ -364,17 +340,7 @@ class BasicBlock: raise Exception("Attempting to call BasicBlock.dominator_tree_children when BinaryView is None") count = ctypes.c_ulonglong() - blocks = core.BNGetBasicBlockDominatorTreeChildren(self.handle, count, False) - assert blocks is not None, "core.BNGetBasicBlockDominatorTreeChildren returned None" - result = [] - try: - for i in range(0, count.value): - handle = core.BNNewBasicBlockReference(blocks[i]) - assert handle is not None - result.append(self._create_instance(handle, self.view)) - return result - finally: - core.BNFreeBasicBlockList(blocks, count.value) + return self._make_blocks(core.BNGetBasicBlockDominatorTreeChildren(self.handle, count, False), count.value) @property def post_dominator_tree_children(self) -> List['BasicBlock']: @@ -383,17 +349,7 @@ class BasicBlock: raise Exception("Attempting to call BasicBlock.post_dominator_tree_children when BinaryView is None") count = ctypes.c_ulonglong() - blocks = core.BNGetBasicBlockDominatorTreeChildren(self.handle, count, True) - assert blocks is not None, "core.BNGetBasicBlockDominatorTreeChildren returned None" - result = [] - try: - for i in range(0, count.value): - handle = core.BNNewBasicBlockReference(blocks[i]) - assert handle is not None - result.append(self._create_instance(handle, self.view)) - return result - finally: - core.BNFreeBasicBlockList(blocks, count.value) + return self._make_blocks(core.BNGetBasicBlockDominatorTreeChildren(self.handle, count, True), count.value) @property def dominance_frontier(self) -> List['BasicBlock']: @@ -402,17 +358,7 @@ class BasicBlock: raise Exception("Attempting to call BasicBlock.dominance_frontier when BinaryView is None") count = ctypes.c_ulonglong() - blocks = core.BNGetBasicBlockDominanceFrontier(self.handle, count, False) - assert blocks is not None, "core.BNGetBasicBlockDominanceFrontier returned None" - result = [] - try: - for i in range(0, count.value): - handle = core.BNNewBasicBlockReference(blocks[i]) - assert handle is not None - result.append(self._create_instance(handle, self.view)) - return result - finally: - core.BNFreeBasicBlockList(blocks, count.value) + return self._make_blocks(core.BNGetBasicBlockDominanceFrontier(self.handle, count, False), count.value) @property def post_dominance_frontier(self) -> List['BasicBlock']: @@ -420,17 +366,7 @@ class BasicBlock: if self.view is None: raise Exception("Attempting to call BasicBlock.post_dominance_frontier when BinaryView is None") count = ctypes.c_ulonglong() - blocks = core.BNGetBasicBlockDominanceFrontier(self.handle, count, True) - assert blocks is not None, "core.BNGetBasicBlockDominanceFrontier returned None" - result = [] - try: - for i in range(0, count.value): - handle = core.BNNewBasicBlockReference(blocks[i]) - assert handle is not None - result.append(self._create_instance(handle, self.view)) - return result - finally: - core.BNFreeBasicBlockList(blocks, count.value) + return self._make_blocks(core.BNGetBasicBlockDominanceFrontier(self.handle, count, True), count.value) @property def annotations(self) -> List[List['_function.InstructionTextToken']]: @@ -564,7 +500,7 @@ class BasicBlock: :param HighlightStandardColor or HighlightColor color: Color value to use for highlighting :Example: - >>> current_basic_block.set_user_highlight(HighlightColor(red=0xff, blue=0xff, green=0)) + >>> current_basic_block.set_user_highlight(_highlight.HighlightColor(red=0xff, blue=0xff, green=0)) >>> current_basic_block.set_user_highlight(HighlightStandardColor.BlueHighlightColor) """ if not isinstance(color, HighlightStandardColor) and not isinstance(color, _highlight.HighlightColor): diff --git a/python/binaryview.py b/python/binaryview.py index b02f5d1a..e61e573c 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -894,7 +894,7 @@ class BinaryViewType(metaclass=_BinaryViewTypeMetaclass): return bv def parse(self, data:'BinaryView') -> Optional['BinaryView']: - view = core.BNParseBinaryViewOfType(self.handle, data.handle) + view = core.BNParseBinaryViewOfType(self, data.handle) if view is None: return None return BinaryView(file_metadata=data.file, handle=view) @@ -1219,7 +1219,7 @@ class TagType: @property def type(self) -> TagTypeType: """Type from enums.TagTypeType""" - return core.BNTagTypeGetType(self.handle) + return TagTypeType(core.BNTagTypeGetType(self.handle)) @type.setter def type(self, value:TagTypeType) -> None: @@ -2709,7 +2709,7 @@ class BinaryView: """ return 0 - def perform_remove(self, addr:int, length:bytes) -> int: + def perform_remove(self, addr:int, length:int) -> int: """ ``perform_remove`` implements a mapping between a virtual address and an absolute file offset, removing ``length`` bytes from the rebased address ``addr``. @@ -2719,7 +2719,7 @@ class BinaryView: .. warning:: This method **must not** be called directly. :param int addr: a virtual address - :param bytes data: the data to be removed + :param int length: the number of bytes to be removed :return: length of data removed, should return 0 on error :rtype: int """ @@ -3097,8 +3097,7 @@ class BinaryView: """ if not (isinstance(data, bytes) or isinstance(data, bytearray) or isinstance(data, str)): raise TypeError("Must be bytes, bytearray, or str") - else: - buf = databuffer.DataBuffer(data) + buf = databuffer.DataBuffer(data) if except_on_relocation and self.range_contains_relocation(addr, addr + len(data)): raise RelocationWriteException("Attempting to write to a location which has a relocation") @@ -3585,7 +3584,7 @@ class BinaryView: finally: core.BNFreeFunctionList(funcs, count.value) - def get_functions_by_name(self, name:str, plat:Optional['_platform.Platform']=None, ordered_filter:List[SymbolType]=[]) -> List['_function.Function']: + def get_functions_by_name(self, name:str, plat:Optional['_platform.Platform']=None, ordered_filter:Optional[List[SymbolType]]=None) -> List['_function.Function']: """``get_functions_by_name`` returns a list of Function objects function with a Symbol of ``name``. @@ -3600,10 +3599,11 @@ class BinaryView: [<func: x86_64@0x1587>] >>> """ - if ordered_filter == []: + if ordered_filter is None: ordered_filter = [SymbolType.FunctionSymbol, SymbolType.ImportedFunctionSymbol, SymbolType.LibraryFunctionSymbol] + if plat == None: plat = self.platform fns = [] @@ -3913,7 +3913,7 @@ class BinaryView: size = refs[i].size typeObj = None if refs[i].incomingType.type: - typeObj = _types.Type(core.BNNewTypeReference(refs[i].incomingType.type),\ + typeObj = _types.Type(core.BNNewTypeReference(refs[i].incomingType.type), confidence = refs[i].incomingType.confidence) yield _types.TypeFieldReference(func, arch, addr, size, typeObj) finally: @@ -4270,7 +4270,7 @@ class BinaryView: try: result = [] for i in range(0, count.value): - typeObj = _types.Type.create(core.BNNewTypeReference(refs[i].type),\ + typeObj = _types.Type.create(core.BNNewTypeReference(refs[i].type), confidence = refs[i].confidence) result.append(typeObj) return result @@ -4291,7 +4291,7 @@ class BinaryView: if not result.type: raise Exception("BNCreateStructureMemberFromAccess failed to create struct member offsets") - return _types.Type.create(core.BNNewTypeReference(result.type),\ + return _types.Type.create(core.BNNewTypeReference(result.type), confidence = result.confidence) def get_callers(self, addr:int) -> Generator[ReferenceSource, None, None]: @@ -4405,7 +4405,7 @@ class BinaryView: return None return _types.CoreSymbol(sym) - def get_symbols_by_name(self, name:str, namespace:'_types.NameSpaceType'=None, ordered_filter:List[SymbolType]=[]) -> List['_types.CoreSymbol']: + def get_symbols_by_name(self, name:str, namespace:'_types.NameSpaceType'=None, ordered_filter:Optional[List[SymbolType]]=None) -> List['_types.CoreSymbol']: """ ``get_symbols_by_name`` retrieves a list of Symbol objects for the given symbol name and ordered filter @@ -4421,7 +4421,7 @@ class BinaryView: [<FunctionSymbol: "public: static enum Foobar::foo __cdecl Foobar::testf(enum Foobar::foo)" @ 0x10001100>] >>> """ - if ordered_filter == []: + if ordered_filter is None: ordered_filter = [SymbolType.FunctionSymbol, SymbolType.ImportedFunctionSymbol, SymbolType.LibraryFunctionSymbol, @@ -4429,6 +4429,7 @@ class BinaryView: SymbolType.ImportedDataSymbol, SymbolType.ImportAddressSymbol, SymbolType.ExternalSymbol] + _namespace = _types.NameSpace.get_core_struct(namespace) count = ctypes.c_ulonglong(0) syms = core.BNGetSymbolsByName(self.handle, name, count, _namespace) @@ -4704,7 +4705,7 @@ class BinaryView: ``create_tag`` creates a new Tag object but does not add it anywhere. Use :py:meth:`create_user_data_tag` to create and add in one step. - :param TagType type: The Tag Type for this Tag + :param TagType tag_type: The Tag Type for this Tag :param str data: Additional data for the Tag :param bool user: Whether or not a user tag :return: The created Tag @@ -6456,7 +6457,7 @@ class BinaryView: raise TypeError("settings parameter is not DisassemblySettings type") result = ctypes.c_ulonglong() - if not core.BNFindNextText(self.handle, start, text, result, settings.handle, flags,\ + if not core.BNFindNextText(self.handle, start, text, result, settings.handle, flags, graph_type): return None return result.value @@ -6480,7 +6481,7 @@ class BinaryView: raise TypeError("settings parameter is not DisassemblySettings type") result = ctypes.c_ulonglong() - if not core.BNFindNextConstant(self.handle, start, constant, result, settings.handle,\ + if not core.BNFindNextConstant(self.handle, start, constant, result, settings.handle, graph_type): return None return result.value @@ -6803,7 +6804,7 @@ class BinaryView: """ core.BNShowHTMLReport(self.handle, title, contents, plaintext) - def show_graph_report(self, title:int, graph:flowgraph.FlowGraph) -> None: + def show_graph_report(self, title:str, graph:flowgraph.FlowGraph) -> None: """ ``show_graph_report`` displays a :py:Class:`FlowGraph` object `graph` in a new tab with ``title``. @@ -7119,7 +7120,7 @@ class BinaryView: result.append(names[i]) return result finally: - core.BNFreeStringList(names, count) + core.BNFreeStringList(names, count.value) def get_load_settings(self, type_name:str) -> Optional[settings.Settings]: """ @@ -7277,7 +7278,7 @@ class BinaryReader: :setter: sets the endianness of the reader (BigEndian or LittleEndian) :type: Endianness """ - return core.BNGetBinaryReaderEndianness(self._handle) + return Endianness(core.BNGetBinaryReaderEndianness(self._handle)) @endianness.setter def endianness(self, value:Endianness) -> None: @@ -7667,11 +7668,11 @@ class BinaryWriter: def offset(self, value:int) -> None: core.BNSeekBinaryWriter(self._handle, value) - def write(self, value, address:Optional[int]=None, except_on_relocation=True) -> bool: + def write(self, value:bytes, address:Optional[int]=None, except_on_relocation=True) -> bool: """ ``write`` writes ``len(value)`` bytes to the internal offset, without regard to endianness. - :param str value: bytes to be written at current offset + :param str bytes: bytes to be written at current offset :param int address: offset to set the internal offset before writing :param bool except_on_relocation: (default True) raise exception when write overlaps a relocation :return: boolean True on success, False on failure. @@ -7689,7 +7690,8 @@ class BinaryWriter: if except_on_relocation and self._view.range_contains_relocation(self.offset, self.offset + len(value)): raise RelocationWriteException("Attempting to write to a location which has a relocation") - value = value.decode("utf-8") + if isinstance(value, str): + value = value.decode("utf-8") buf = ctypes.create_string_buffer(len(value)) ctypes.memmove(buf, value, len(value)) return core.BNWriteData(self._handle, buf, len(value)) diff --git a/python/databuffer.py b/python/databuffer.py index 9346f660..fea7bb82 100644 --- a/python/databuffer.py +++ b/python/databuffer.py @@ -26,7 +26,7 @@ from . import _binaryninjacore as core DataBufferInputType = Union[str, bytes, 'DataBuffer', int] class DataBuffer: - def __init__(self, contents:bytes=b"", handle=None): + def __init__(self, contents:Union[str, bytes, 'DataBuffer', int]=b"", handle=None): if handle is not None: self.handle = core.handle_of_type(handle, core.BNDataBuffer) elif isinstance(contents, int): @@ -36,6 +36,7 @@ class DataBuffer: elif isinstance(contents, str): self.handle = core.BNCreateDataBuffer(contents.encode("utf-8"), len(contents.encode("utf-8"))) else: + assert isinstance(contents, bytes) self.handle = core.BNCreateDataBuffer(contents, len(contents)) def __del__(self): @@ -67,10 +68,10 @@ class DataBuffer: return bytes(self)[i] elif i < 0: if i >= -len(self): - return core.BNGetDataBufferByte(self.handle, int(len(self) + i)) + return core.BNGetDataBufferByte(self.handle, int(len(self) + i)).to_bytes(1, "little") raise IndexError("index out of range") elif i < len(self): - return core.BNGetDataBufferByte(self.handle, int(i)) + return core.BNGetDataBufferByte(self.handle, int(i)).to_bytes(1, "little") else: raise IndexError("index out of range") @@ -139,13 +140,13 @@ class DataBuffer: return core.BNDataBufferToEscapedString(self.handle) def unescape(self) -> 'DataBuffer': - return DataBuffer(handle=core.BNDecodeEscapedString(bytes(self))) + return DataBuffer(handle=core.BNDecodeEscapedString(str(self))) def base64_encode(self) -> str: return core.BNDataBufferToBase64(self.handle) def base64_decode(self) -> 'DataBuffer': - return DataBuffer(handle = core.BNDecodeBase64(bytes(self))) + return DataBuffer(handle = core.BNDecodeBase64(str(self))) def zlib_compress(self) -> Optional['DataBuffer']: buf = core.BNZlibCompress(self.handle) diff --git a/python/demangle.py b/python/demangle.py index 6d8fba27..3f22d294 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -131,7 +131,7 @@ def simplify_name_to_qualified_name(input_name, simplify = True): :param input_name: String or qualified name to be simplified :type input_name: Union[str, QualifiedName] - :param bool simplify_name: (optional) Whether to simplify input string (no effect if given a qualified name; will always simplify) + :param bool simplify: (optional) Whether to simplify input string (no effect if given a qualified name; will always simplify) :return: simplified name (or one-element array containing the input if simplifier fails/cannot simplify) :rtype: QualifiedName :Example: diff --git a/python/filemetadata.py b/python/filemetadata.py index aea68bb6..c9f9a050 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -508,5 +508,5 @@ class FileMetadata: views = [] for i in range(length.value): views.append(result[i].decode("utf-8")) - core.BNFreeStringList(result, length) + core.BNFreeStringList(result, length.value) return views diff --git a/python/function.py b/python/function.py index d3b9ea88..3fbe90c0 100644 --- a/python/function.py +++ b/python/function.py @@ -21,8 +21,8 @@ import ctypes import inspect -from typing import Generator, Optional, List, Tuple, Union, Mapping, Any -from dataclasses import dataclass, field +from typing import Generator, Optional, List, Tuple, Union, Mapping, Any, Dict +from dataclasses import dataclass # Binary Ninja components from . import _binaryninjacore as core @@ -285,7 +285,7 @@ class TagList: address = self._tags[self._n].addr assert core_tag is not None, "core.BNNewTagReference returned None" self._n += 1 - return (arch, address, binaryview.Tag(core_tag)) + return arch, address, binaryview.Tag(core_tag) def __getitem__(self, i:Union[int, slice]) -> Union[Tuple['architecture.Architecture', int, 'binaryview.Tag'], List[Tuple['architecture.Architecture', int, 'binaryview.Tag']]]: if isinstance(i, int): @@ -297,7 +297,7 @@ class TagList: core_tag = core.BNNewTagReference(self._tags[i].tag) arch = architecture.CoreArchitecture._from_cache(self._tags[i].arch) assert core_tag is not None, "core.BNNewTagReference returned None" - return (arch, self._tags[i].addr, binaryview.Tag(core_tag)) + return arch, self._tags[i].addr, binaryview.Tag(core_tag) elif isinstance(i, slice): result = [] if i.start < 0 or i.start >= len(self) or i.stop < 0 or i.stop >= len(self): @@ -314,6 +314,15 @@ class TagList: class Function: _associated_data = {} + """ + The examples in the following code will use the following variables + + >>> from binaryninja import * + >>> bv = binaryninja.binaryview.BinaryViewType.get_view_of_file("/bin/ls") + >>> current_function = bv.functions[0] + >>> here = current_function.start + """ + def __init__(self, view:Optional['binaryview.BinaryView']=None, handle:Optional[core.BNFunctionHandle]=None): self._advanced_analysis_requests = 0 @@ -533,7 +542,7 @@ class Function: count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) assert blocks is not None, "core.BNGetFunctionBasicBlockList returned None" - return (count, blocks) + return count, blocks def _instantiate_block(self, handle): return basicblock.BasicBlock(handle, self.view) @@ -571,6 +580,7 @@ class Function: :param TagType type: The Tag Type for this Tag :param str data: Additional data for the Tag + :param bool user: Boolean indicating if this is a user tag or not :return: The created Tag :rtype: Tag :Example: @@ -1216,7 +1226,7 @@ class Function: @comment.setter def comment(self, comment:str) -> None: """Sets a comment for the current function""" - return core.BNSetFunctionComment(self.handle, comment) + core.BNSetFunctionComment(self.handle, comment) @property def llil_basic_blocks(self) -> Generator['lowlevelil.LowLevelILBasicBlock', None, None]: @@ -1236,7 +1246,7 @@ class Function: for block in self.basic_blocks: start = block.start for i in block: - yield (i[0], start) + yield i[0], start start += i[1] @property @@ -1435,7 +1445,7 @@ class Function: from_arch = self.arch _name = types.QualifiedName(name)._to_core_struct() - core.BNAddUserTypeFieldReference(self.handle, from_arch.handle, from_addr, _name,\ + core.BNAddUserTypeFieldReference(self.handle, from_arch.handle, from_addr, _name, offset, size) def remove_user_type_field_ref(self, from_addr:int, name:'types.QualifiedNameType', offset:int, @@ -1463,7 +1473,7 @@ class Function: from_arch = self.arch _name = types.QualifiedName(name)._to_core_struct() - core.BNRemoveUserTypeFieldReference(self.handle, from_arch.handle, from_addr, _name,\ + core.BNRemoveUserTypeFieldReference(self.handle, from_arch.handle, from_addr, _name, offset, size) def get_low_level_il_at(self, addr:int, arch:Optional['architecture.Architecture']=None) -> Optional['lowlevelil.LowLevelILInstruction']: @@ -1567,7 +1577,7 @@ class Function: :rtype: variable.RegisterValue :Example: - >>> func.get_reg_value_at(0x400dbe, 'rdi') + >>> current_function.get_reg_value_at(0x400dbe, 'rdi') <const 0x2> """ if arch is None: @@ -1580,7 +1590,7 @@ class Function: return result @property - def auto_address_tags(self) -> List['binaryview.Tag']: + def auto_address_tags(self) -> List[Tuple['architecture.Architecture', int, 'binaryview.Tag']]: """ ``auto_address_tags`` gets a list of all auto-defined address Tags in the function. Tags are returned as a list of (arch, address, Tag) tuples. @@ -1632,12 +1642,11 @@ class Function: :rtype: variable.RegisterValue :Example: - >>> func.get_reg_value_after(0x400dbe, 'rdi') + >>> current_function.get_reg_value_after(0x400dbe, 'rdi') <undetermined> """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_reg_value_after for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch reg = arch.get_reg_index(reg) value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg) @@ -1654,8 +1663,7 @@ class Function: :rtype: list(Tag) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_auto_address_tags_at for function with no architecture specified") + assert self.arch is not None, "Can't call get_auto_address_tags_at for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() tags = core.BNGetAutoAddressTags(self.handle, arch.handle, addr, count) @@ -1678,8 +1686,7 @@ class Function: :rtype: list(Tag) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_user_address_tags_at for function with no architecture specified") + assert self.arch is not None, "Can't call get_user_address_tags_at for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() tags = core.BNGetUserAddressTags(self.handle, arch.handle, addr, count) @@ -1703,9 +1710,8 @@ class Function: :rtype: list(Tag) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_address_tags_of_type for function with no architecture specified") - arch = self.arch + assert self.arch is not None, "Can't call get_address_tags_of_type for function with no architecture specified" + arch = self.arch count = ctypes.c_ulonglong() tags = core.BNGetAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle, count) assert tags is not None, "core.BNGetAddressTagsOfType returned None" @@ -1728,8 +1734,7 @@ class Function: :rtype: list(Tag) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_auto_address_tags_of_type for function with no architecture specified") + assert self.arch is not None, "Can't call get_auto_address_tags_of_type for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() tags = core.BNGetAutoAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle, count) @@ -1753,8 +1758,7 @@ class Function: :rtype: list(Tag) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_user_address_tags_of_type for function with no architecture specified") + assert self.arch is not None, "Can't get_user_address_tags_of_type for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() tags = core.BNGetUserAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle, count) @@ -1778,8 +1782,7 @@ class Function: :rtype: list((Architecture, int, Tag)) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_address_tags_in_range for function with no architecture specified") + assert self.arch is not None, "Can't call get_address_tags_in_range for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() refs = core.BNGetAddressTagsInRange(self.handle, arch.handle, address_range.start, address_range.end, count) @@ -1804,8 +1807,7 @@ class Function: :rtype: list((Architecture, int, Tag)) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_auto_address_tags_in_range for function with no architecture specified") + assert self.arch is not None, "Can't call get_auto_address_tags_in_range for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() refs = core.BNGetAutoAddressTagsInRange(self.handle, arch.handle, address_range.start, address_range.end, count) @@ -1830,8 +1832,7 @@ class Function: :rtype: list((Architecture, int, Tag)) """ if arch is None: - if self.arch is None: - raise Exception("Can't call get_user_address_tags_in_range for function with no architecture specified") + assert self.arch is not None, "Can't call get_user_address_tags_in_range for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() refs = core.BNGetUserAddressTagsInRange(self.handle, arch.handle, address_range.start, address_range.end, count) @@ -1862,12 +1863,11 @@ class Function: :Example: - >>> func.get_stack_contents_at(0x400fad, -16, 4) + >>> current_function.get_stack_contents_at(0x400fad, -16, 4) <range: 0x8 to 0xffffffff> """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch value = core.BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size) result = variable.RegisterValue.from_BNRegisterValue(value, arch) @@ -1876,8 +1876,7 @@ class Function: def get_stack_contents_after(self, addr:int, offset:int, size:int, arch:Optional['architecture.Architecture']=None) -> 'variable.RegisterValue': if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size) result = variable.RegisterValue.from_BNRegisterValue(value, arch) @@ -1886,8 +1885,7 @@ class Function: def get_parameter_at(self, addr:int, func_type:Optional['types.Type'], i:int, arch:Optional['architecture.Architecture']=None) -> 'variable.RegisterValue': if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch _func_type = None @@ -1908,8 +1906,7 @@ class Function: :rtype: None """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch core.BNRemoveUserAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle) @@ -1924,8 +1921,7 @@ class Function: def get_regs_read_by(self, addr:int, arch:Optional['architecture.Architecture']=None) -> List['architecture.RegisterName']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() regs = core.BNGetRegistersReadByInstruction(self.handle, arch.handle, addr, count) @@ -1938,8 +1934,7 @@ class Function: def get_regs_written_by(self, addr:int, arch:Optional['architecture.Architecture']=None) -> List['architecture.RegisterName']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() regs = core.BNGetRegistersWrittenByInstruction(self.handle, arch.handle, addr, count) @@ -1960,8 +1955,7 @@ class Function: :rtype: None """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call remove_auto_address_tag with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch core.BNRemoveAutoAddressTag(self.handle, arch.handle, addr, tag.handle) @@ -1975,16 +1969,14 @@ class Function: :rtype: None """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch core.BNRemoveAutoAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle) def get_stack_vars_referenced_by(self, addr:int, arch:Optional['architecture.Architecture']=None) -> List['variable.StackVariableReference']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) @@ -2037,8 +2029,7 @@ class Function: def get_lifted_il_at(self, addr:int, arch:Optional['architecture.Architecture']=None) -> Optional['lowlevelil.LowLevelILInstruction']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch idx = core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr) @@ -2062,8 +2053,7 @@ class Function: [<il: push(rbp)>] """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILInstructionsForAddress(self.handle, arch.handle, addr, count) @@ -2144,8 +2134,7 @@ class Function: def get_constants_referenced_by(self, addr:int, arch:'architecture.Architecture'=None) -> List[variable.ConstantReference]: if arch is None: - if self.arch is None: - raise Exception(f"Can't call get_constants_referenced_by with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() refs = core.BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, count) @@ -2176,8 +2165,7 @@ class Function: def get_lifted_il_flag_uses_for_definition(self, i:'lowlevelil.InstructionIndex', flag:'architecture.FlagType') -> List['lowlevelil.LowLevelILInstruction']: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" flag = self.arch.get_flag_index(flag) count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILFlagUsesForDefinition(self.handle, i, flag, count) @@ -2190,8 +2178,7 @@ class Function: def get_lifted_il_flag_definitions_for_use(self, i:'lowlevelil.InstructionIndex', flag:'architecture.FlagType') -> List['lowlevelil.InstructionIndex']: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" flag = self.arch.get_flag_index(flag) count = ctypes.c_ulonglong() @@ -2204,9 +2191,8 @@ class Function: return result def get_flags_read_by_lifted_il_instruction(self, i:'lowlevelil.InstructionIndex') -> \ - List['architecture.RegisterName']: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + List['architecture.FlagName']: + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" count = ctypes.c_ulonglong() flags = core.BNGetFlagsReadByLiftedILInstruction(self.handle, i, count) @@ -2220,8 +2206,7 @@ class Function: def get_flags_written_by_lifted_il_instruction(self, i:'lowlevelil.InstructionIndex') -> \ List['architecture.FlagName']: count = ctypes.c_ulonglong() - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" flags = core.BNGetFlagsWrittenByLiftedILInstruction(self.handle, i, count) assert flags is not None, "core.BNGetFlagsWrittenByLiftedILInstruction returned None" @@ -2252,8 +2237,7 @@ class Function: def set_auto_indirect_branches(self, source:int, branches:List[Tuple['architecture.Architecture', int]], source_arch:Optional['architecture.Architecture']=None) -> None: if source_arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" source_arch = self.arch branch_list = (core.BNArchitectureAndAddress * len(branches))() for i in range(len(branches)): @@ -2264,8 +2248,7 @@ class Function: def set_user_indirect_branches(self, source:int, branches:List[Tuple['architecture.Architecture', int]], source_arch:Optional['architecture.Architecture']=None) -> None: if source_arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" source_arch = self.arch branch_list = (core.BNArchitectureAndAddress * len(branches))() for i in range(len(branches)): @@ -2275,8 +2258,7 @@ class Function: def get_indirect_branches_at(self, addr:int, arch:Optional['architecture.Architecture']=None) -> List['variable.IndirectBranchInfo']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count) @@ -2448,8 +2430,7 @@ class Function: :param Architecture arch: (optional) Architecture of the instruction or IL line containing the token """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch return IntegerDisplayType(core.BNGetIntegerConstantDisplayType(self.handle, arch.handle, instr_addr, value, operand)) @@ -2463,8 +2444,7 @@ class Function: :param Architecture arch: (optional) Architecture of the instruction or IL line containing the token """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch if isinstance(display_type, str): display_type = IntegerDisplayType[display_type] @@ -2498,8 +2478,7 @@ class Function: <block: x86_64@0x100000f30-0x100000f50> """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch block = core.BNGetFunctionBasicBlockAtAddress(self.handle, arch.handle, addr) if not block: @@ -2514,8 +2493,7 @@ class Function: <color: #ff00ff> """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch color = core.BNGetInstructionHighlight(self.handle, arch.handle, addr) if color.style == HighlightColorStyle.StandardHighlightColor: @@ -2538,8 +2516,7 @@ class Function: :param Architecture arch: (optional) Architecture of the instruction if different from self.arch """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch if not isinstance(color, HighlightStandardColor) and not isinstance(color, _highlight.HighlightColor): raise ValueError("Specified color is not one of HighlightStandardColor, _highlight.HighlightColor") @@ -2562,8 +2539,7 @@ class Function: >>> current_function.set_user_instr_highlight(here, highlight.HighlightColor(red=0xff, blue=0xff, green=0)) """ if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch if not isinstance(color, HighlightStandardColor) and not isinstance(color, _highlight.HighlightColor): raise ValueError("Specified color is not one of HighlightStandardColor, highlight.HighlightColor") @@ -2612,8 +2588,7 @@ class Function: def get_stack_var_at_frame_offset(self, offset:int, addr:int, arch:Optional['architecture.Architecture']=None) -> \ Optional['variable.Variable']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch found_var = core.BNVariableNameAndType() if not core.BNGetStackVariableAtFrameOffset(self.handle, arch.handle, addr, offset, found_var): @@ -2645,21 +2620,19 @@ class Function: result = core.BNGetFunctionRegisterValueAtExit(self.handle, self.arch.get_reg_index(reg)) return variable.RegisterValue.from_BNRegisterValue(result, self.arch) - def set_auto_call_stack_adjustment(self, addr:int, adjust:Union[int, 'types.SizeWithConfidence'],\ + def set_auto_call_stack_adjustment(self, addr:int, adjust:Union[int, 'types.SizeWithConfidence'], arch:Optional['architecture.Architecture']=None) -> None: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch if not isinstance(adjust, types.SizeWithConfidence): adjust = types.SizeWithConfidence(adjust) core.BNSetAutoCallStackAdjustment(self.handle, arch.handle, addr, adjust.value, adjust.confidence) - def set_auto_call_reg_stack_adjustment(self, addr:int, adjust:Mapping['architecture.RegisterStackName', int],\ + def set_auto_call_reg_stack_adjustment(self, addr:int, adjust:Mapping['architecture.RegisterStackName', int], arch:Optional['architecture.Architecture']=None) -> None: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch adjust_buf = (core.BNRegisterStackAdjustment * len(adjust))() i = 0 @@ -2676,8 +2649,7 @@ class Function: def set_auto_call_reg_stack_adjustment_for_reg_stack(self, addr:int, reg_stack:'architecture.RegisterStackType', adjust, arch:Optional['architecture.Architecture']=None) -> None: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch reg_stack = arch.get_reg_stack_index(reg_stack) if not isinstance(adjust, types.RegisterStackAdjustmentWithConfidence): @@ -2690,8 +2662,7 @@ class Function: if isinstance(adjust_type, str): (adjust_type, _) = self.view.parse_type_string(adjust_type) if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch if adjust_type is None: tc = None @@ -2702,8 +2673,7 @@ class Function: def set_call_stack_adjustment(self, addr:int, adjust:Union[int, 'types.SizeWithConfidence'], arch:Optional['architecture.Architecture']=None): if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch if not isinstance(adjust, types.SizeWithConfidence): adjust = types.SizeWithConfidence(adjust) @@ -2713,8 +2683,7 @@ class Function: adjust:Mapping['architecture.RegisterStackName', 'types.RegisterStackAdjustmentWithConfidence'], arch:Optional['architecture.Architecture']=None) -> None: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch adjust_buf = (core.BNRegisterStackAdjustment * len(adjust))() i = 0 @@ -2722,7 +2691,7 @@ class Function: adjust_buf[i].regStack = arch.get_reg_stack_index(reg_stack) value = adjust[reg_stack] if not isinstance(value, types.RegisterStackAdjustmentWithConfidence): - value = types.RegisterStackAdjustmentWithConfidence(value) + value = types.RegisterStackAdjustmentWithConfidence(int(value)) adjust_buf[i].adjustment = value.value adjust_buf[i].confidence = value.confidence i += 1 @@ -2731,8 +2700,7 @@ class Function: def set_call_reg_stack_adjustment_for_reg_stack(self, addr:int, reg_stack:'architecture.RegisterStackType', adjust:Union[int, 'types.RegisterStackAdjustmentWithConfidence'], arch:Optional['architecture.Architecture']=None) -> None: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch reg_stack = arch.get_reg_stack_index(reg_stack) if not isinstance(adjust, types.RegisterStackAdjustmentWithConfidence): @@ -2742,8 +2710,7 @@ class Function: def get_call_type_adjustment(self, addr:int, arch:Optional['architecture.Architecture']=None) -> Optional['types.Type']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch result = core.BNGetCallTypeAdjustment(self.handle, arch.handle, addr) if not result.type: @@ -2753,17 +2720,15 @@ class Function: def get_call_stack_adjustment(self, addr:int, arch:Optional['architecture.Architecture']=None) -> 'types.SizeWithConfidence': if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch result = core.BNGetCallStackAdjustment(self.handle, arch.handle, addr) return types.SizeWithConfidence(result.value, confidence = result.confidence) def get_call_reg_stack_adjustment(self, addr:int, arch:Optional['architecture.Architecture']=None) -> \ - Mapping['architecture.RegisterName', 'types.RegisterStackAdjustmentWithConfidence']: + Dict['architecture.RegisterStackName', 'types.RegisterStackAdjustmentWithConfidence']: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch count = ctypes.c_ulonglong() adjust = core.BNGetCallRegisterStackAdjustment(self.handle, arch.handle, addr, count) @@ -2775,11 +2740,10 @@ class Function: core.BNFreeRegisterStackAdjustments(adjust) return result - def get_call_reg_stack_adjustment_for_reg_stack(self, addr:int, reg_stack:'architecture.RegisterStackType',\ + def get_call_reg_stack_adjustment_for_reg_stack(self, addr:int, reg_stack:'architecture.RegisterStackType', arch:Optional['architecture.Architecture']=None) -> 'types.RegisterStackAdjustmentWithConfidence': if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch reg_stack = arch.get_reg_stack_index(reg_stack) adjust = core.BNGetCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack) @@ -2788,8 +2752,7 @@ class Function: def is_call_instruction(self, addr:int, arch:Optional['architecture.Architecture']=None) -> bool: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch return core.BNIsCallInstruction(self.handle, arch.handle, addr) @@ -2810,10 +2773,10 @@ class Function: :Example: - >>> var = current_mlil[0].operands[0] - >>> def_site = 0x40108d - >>> value = PossibleValueSet.constant(5) - >>> current_function.set_user_var_value(var, def_site, value) + >>> mlil_var = current_mlil[0].operands[0] + >>> def_address = 0x40108d + >>> var_value = PossibleValueSet.constant(5) + >>> current_function.set_user_var_value(mlil_var, def_address, var_value) """ if self.arch is None: raise Exception("can not set_user_var_value if Function.arch is None") @@ -2872,7 +2835,6 @@ class Function: var_values = core.BNGetAllUserVariableValues(self.handle, count) assert var_values is not None, "core.BNGetAllUserVariableValues returned None" result = {} - i = 0 for i in range(count.value): var_val = var_values[i] var = variable.Variable.from_BNVariable(self, var_val.var) @@ -2968,7 +2930,7 @@ class Function: return result @property - def callers(self) -> List[int]: + def callers(self) -> List['Function']: """ ``callers`` returns a list of functions that call this function Does not point to the actual address where the call occurs, just the start of the function that contains the call. @@ -3003,8 +2965,8 @@ class Function: :rtype: list(ILReferenceSource) :Example: - >>> var = current_mlil[0].operands[0] - >>> current_function.get_mlil_var_refs(var) + >>> mlil_var = current_mlil[0].operands[0] + >>> current_function.get_mlil_var_refs(mlil_var) """ count = ctypes.c_ulonglong(0) refs = core.BNGetMediumLevelILVariableReferences(self.handle, var.to_BNVariable(), count) @@ -3046,8 +3008,7 @@ class Function: count = ctypes.c_ulonglong(0) if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch if length is None: @@ -3083,8 +3044,8 @@ class Function: :rtype: list(ILReferenceSource) :Example: - >>> var = current_hlil[0].operands[0] - >>> current_function.get_hlil_var_refs(var) + >>> mlil_var = current_hlil[0].operands[0] + >>> current_function.get_hlil_var_refs(mlil_var) """ count = ctypes.c_ulonglong(0) refs = core.BNGetHighLevelILVariableReferences(self.handle, var.to_BNVariable(), count) @@ -3149,8 +3110,7 @@ class Function: def get_instruction_containing_address(self, addr:int, arch:Optional['architecture.Architecture']=None) -> \ Optional[int]: if arch is None: - if self.arch is None: - raise Exception(f"Can't call {_function_name_()} for function with no architecture specified") + assert self.arch is not None, f"Can't call {_function_name_()} for function with no architecture specified" arch = self.arch start = ctypes.c_ulonglong() @@ -3281,7 +3241,7 @@ class DisassemblyTextRenderer: return architecture.CoreArchitecture._from_cache(handle = core.BNGetDisassemblyTextRendererArchitecture(self.handle)) @arch.setter - def arch(self, arch='architecture.Architecture') -> None: + def arch(self, arch:'architecture.Architecture') -> None: core.BNSetDisassemblyTextRendererArchitecture(self.handle, arch.handle) @property @@ -3384,7 +3344,6 @@ class DisassemblyTextRenderer: line_buf[i].count = len(line.tokens) line_buf[i].tokens = InstructionTextToken._get_core_struct(line.tokens) count = ctypes.c_ulonglong() - lines = ctypes.POINTER(core.BNDisassemblyTextLine)() lines = core.BNPostProcessDisassemblyTextRendererLines(self.handle, addr, length, line_buf, len(in_lines), count, indent_spaces) assert lines is not None, "core.BNPostProcessDisassemblyTextRendererLines returned None" il_function = self.il_function @@ -3443,7 +3402,7 @@ class DisassemblyTextRenderer: @staticmethod def is_integer_token(token:'InstructionTextToken') -> bool: - return core.BNIsIntegerToken(token) + return core.BNIsIntegerToken(token.type) def add_integer_token(self, tokens:List['InstructionTextToken'], int_token:'InstructionTextToken', addr:int, arch:Optional['architecture.Architecture']=None) -> None: diff --git a/python/highlevelil.py b/python/highlevelil.py index 4298e91f..b757727d 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -20,7 +20,7 @@ import ctypes import struct -from typing import Optional, Generator, List, Union, Any, NewType, Tuple, ClassVar, Mapping +from typing import Optional, Generator, List, Union, NewType, Tuple, ClassVar, Mapping from dataclasses import dataclass from enum import Enum @@ -37,7 +37,6 @@ from . import types from . import highlight from . import flowgraph from . import variable -from .log import log_info from .interaction import show_graph_report from .commonil import (BaseILInstruction, Call, Tailcall, Syscall, Comparison, Signed, UnaryOperation, BinaryOperation, SSA, Phi, Loop, ControlFlow, Memory, Constant, Arithmetic, DoublePrecision, Terminal, @@ -490,7 +489,7 @@ class HighLevelILInstruction(BaseILInstruction): """SSA form of expression (read-only)""" assert self.function.ssa_form is not None return HighLevelILInstruction.create(self.function.ssa_form, - core.BNGetHighLevelILSSAExprIndex(self.function.handle, self.expr_index), self.as_ast) + ExpressionIndex(core.BNGetHighLevelILSSAExprIndex(self.function.handle, self.expr_index)), self.as_ast) @property def non_ssa_form(self) -> Optional['HighLevelILInstruction']: @@ -498,7 +497,7 @@ class HighLevelILInstruction(BaseILInstruction): if self.function.non_ssa_form is None: return None return HighLevelILInstruction.create(self.function.non_ssa_form, - core.BNGetHighLevelILNonSSAExprIndex(self.function.handle, self.expr_index), self.as_ast) + ExpressionIndex(core.BNGetHighLevelILNonSSAExprIndex(self.function.handle, self.expr_index)), self.as_ast) @property def medium_level_il(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: @@ -592,10 +591,12 @@ class HighLevelILInstruction(BaseILInstruction): return types.Type.create(core.BNNewTypeReference(result.type), platform = platform, confidence = result.confidence) return None - def get_possible_values(self, options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + def get_possible_values(self, options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': mlil = self.mlil if mlil is None: return variable.PossibleValueSet() + if options is None: + options = [] return mlil.get_possible_values(options) @property @@ -2123,7 +2124,7 @@ class HighLevelILFunction: raise IndexError("index out of range") if i < 0: i = len(self) + i - return HighLevelILInstruction.create(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False, + return HighLevelILInstruction.create(self, ExpressionIndex(core.BNGetHighLevelILIndexForInstruction(self.handle, i)), False, InstructionIndex(i)) def __setitem__(self, i, j): @@ -2167,7 +2168,7 @@ class HighLevelILFunction: expr_index = core.BNGetHighLevelILRootExpr(self.handle) if expr_index >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction.create(self, expr_index) + return HighLevelILInstruction.create(self, ExpressionIndex(expr_index)) @root.setter def root(self, value:HighLevelILInstruction) -> None: @@ -2177,7 +2178,7 @@ class HighLevelILFunction: count = ctypes.c_ulonglong() blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count) assert blocks is not None, "core.BNGetHighLevelILBasicBlockList returned None" - return (count, blocks) + return count, blocks def _instantiate_block(self, handle): return HighLevelILBasicBlock(handle, self, self.view) @@ -2249,13 +2250,13 @@ class HighLevelILFunction: result = core.BNGetHighLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version) if result >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction.create(self, result) + return HighLevelILInstruction.create(self, ExpressionIndex(result)) def get_ssa_memory_definition(self, version:int) -> Optional[HighLevelILInstruction]: result = core.BNGetHighLevelILSSAMemoryDefinition(self.handle, version) if result >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction.create(self, result) + return HighLevelILInstruction.create(self, ExpressionIndex(result)) def get_ssa_var_uses(self, ssa_var:'mediumlevelil.SSAVariable') -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() @@ -2335,7 +2336,8 @@ class HighLevelILFunction: d:int = 0, e:int = 0, size:int = 0) -> ExpressionIndex: if isinstance(operation, str): operation_value = HighLevelILOperation[operation] - elif isinstance(operation, HighLevelILOperation): + else: + assert isinstance(operation, HighLevelILOperation) operation_value = operation.value return ExpressionIndex(core.BNHighLevelILAddExpr(self.handle, operation_value, size, a, b, c, d, e)) @@ -2450,7 +2452,7 @@ class HighLevelILFunction: result = core.BNGetMediumLevelILExprIndexFromHighLevelIL(self.handle, expr) if result >= core.BNGetMediumLevelILExprCount(medium_il.handle): return None - return result + return mediumlevelil.ExpressionIndex(result) def get_medium_level_il_expr_indexes(self, expr:ExpressionIndex) -> List['mediumlevelil.ExpressionIndex']: count = ctypes.c_ulonglong() @@ -2466,7 +2468,7 @@ class HighLevelILFunction: result = core.BNGetHighLevelILExprIndexForLabel(self.handle, label_idx) if result >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction.create(self, result) + return HighLevelILInstruction.create(self, ExpressionIndex(result)) def get_label_uses(self, label_idx:int) -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() @@ -2509,7 +2511,7 @@ class HighLevelILBasicBlock(basicblock.BasicBlock): def __contains__(self, instruction): if type(instruction) != HighLevelILInstruction or instruction.il_basic_block != self: return False - if instruction.instr_index >= self.start and instruction.instr_index <= self.end: + if self.start <= instruction.instr_index <= self.end: return True else: return False diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index 9c3040c9..f87e8b33 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -246,27 +246,7 @@ class LinearViewObject: next_obj = next_obj.handle count = ctypes.c_ulonglong(0) - lines = core.BNGetLinearViewObjectLines(self.handle, prev_obj, next_obj, count) - assert lines is not None, "core.BNGetLinearViewObjectLines returned None" - - result = [] - for i in range(0, count.value): - func = None - block = None - if lines[i].function: - func = _function.Function(None, core.BNNewFunctionReference(lines[i].function)) - if lines[i].block: - core_block = core.BNNewBasicBlockReference(lines[i].block) - assert core_block is not None, "core.BNNewBasicBlockReference returned None" - block = basicblock.BasicBlock(core_block, None) - color = highlight.HighlightColor._from_core_struct(lines[i].contents.highlight) - addr = lines[i].contents.addr - tokens = _function.InstructionTextToken._from_core_struct(lines[i].contents.tokens, lines[i].contents.count) - contents = _function.DisassemblyTextLine(tokens, addr, color = color) - result.append(LinearDisassemblyLine(lines[i].type, func, block, contents)) - - core.BNFreeLinearDisassemblyLines(lines, count.value) - return result + return LinearViewCursor._make_lines(core.BNGetLinearViewObjectLines(self.handle, prev_obj, next_obj, count), count.value) def ordering_index_for_child(self, child): return core.BNGetLinearViewObjectOrderingIndexForChild(self.handle, child.handle) @@ -570,30 +550,33 @@ class LinearViewCursor: def next(self): return core.BNLinearViewCursorNext(self.handle) + @staticmethod + def _make_lines(lines, count:int) -> List['LinearDisassemblyLine']: + assert lines is not None, "core returned None for LinearDisassembly lines" + try: + result = [] + for i in range(0, count): + func = None + block = None + if lines[i].function: + func = _function.Function(None, core.BNNewFunctionReference(lines[i].function)) + if lines[i].block: + core_block = core.BNNewBasicBlockReference(lines[i].block) + assert core_block is not None, "core.BNNewBasicBlockReference returned None" + block = basicblock.BasicBlock(core_block, None) + color = highlight.HighlightColor._from_core_struct(lines[i].contents.highlight) + addr = lines[i].contents.addr + tokens = _function.InstructionTextToken._from_core_struct(lines[i].contents.tokens, lines[i].contents.count) + contents = _function.DisassemblyTextLine(tokens, addr, color = color) + result.append(LinearDisassemblyLine(lines[i].type, func, block, contents)) + return result + finally: + core.BNFreeLinearDisassemblyLines(lines, count) + @property def lines(self): count = ctypes.c_ulonglong(0) - lines = core.BNGetLinearViewCursorLines(self.handle, count) - assert lines is not None, "core.BNGetLinearViewCursorLines returned None" - - result = [] - for i in range(0, count.value): - func = None - block = None - if lines[i].function: - func = _function.Function(None, core.BNNewFunctionReference(lines[i].function)) - if lines[i].block: - core_block = core.BNNewBasicBlockReference(lines[i].block) - assert core_block is not None, "core.BNNewBasicBlockReference returned None" - block = basicblock.BasicBlock(core_block, None) - color = highlight.HighlightColor._from_core_struct(lines[i].contents.highlight) - addr = lines[i].contents.addr - tokens = _function.InstructionTextToken._from_core_struct(lines[i].contents.tokens, lines[i].contents.count) - contents = _function.DisassemblyTextLine(tokens, addr, color = color) - result.append(LinearDisassemblyLine(lines[i].type, func, block, contents)) - - core.BNFreeLinearDisassemblyLines(lines, count.value) - return result + return LinearViewCursor._make_lines(core.BNGetLinearViewCursorLines(self.handle, count), count.value) def duplicate(self): return LinearViewCursor(None, handle = core.BNDuplicateLinearViewCursor(self.handle)) diff --git a/python/log.py b/python/log.py index c4b74e5c..21e3bae2 100644 --- a/python/log.py +++ b/python/log.py @@ -140,7 +140,7 @@ def log_to_stdout(min_level=LogLevel.InfoLog): """ ``log_to_stdout`` redirects minimum log level to standard out. - :param enums.LogLevel log_level: minimum level to log to + :param enums.LogLevel min_level: minimum level to log to :rtype: None :Example: diff --git a/python/lowlevelil.py b/python/lowlevelil.py index fc3ccb7f..5a326020 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -20,7 +20,7 @@ import ctypes import struct -from typing import Generator, List, Optional, Mapping, Union, Tuple, NewType, ClassVar +from typing import Generator, List, Optional, Dict, Union, Tuple, NewType, ClassVar from dataclasses import dataclass # Binary Ninja components @@ -55,10 +55,10 @@ LowLevelILOperandType = Union[ 'ILIntrinsic', 'ILRegisterStack', int, - Mapping[int, int], + Dict[int, int], float, 'LowLevelILInstruction', - Mapping['architecture.RegisterStackName', int], + Dict['architecture.RegisterStackName', int], 'SSAFlag', 'SSARegister', 'SSARegisterStack', @@ -312,7 +312,7 @@ class LowLevelILInstruction(BaseILInstruction): expr_index:ExpressionIndex instr:CoreLowLevelILInstruction instr_index:Optional[InstructionIndex] - ILOperations:ClassVar[Mapping[LowLevelILOperation, List[Tuple[str,str]]]] = { + ILOperations:ClassVar[Dict[LowLevelILOperation, List[Tuple[str,str]]]] = { LowLevelILOperation.LLIL_NOP: [], LowLevelILOperation.LLIL_SET_REG: [("dest", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SPLIT: [("hi", "reg"), ("lo", "reg"), ("src", "expr")], @@ -556,7 +556,7 @@ class LowLevelILInstruction(BaseILInstruction): ssa_func = self.function.ssa_form assert ssa_func is not None return LowLevelILInstruction.create(ssa_func, - core.BNGetLowLevelILSSAExprIndex(self.function.handle, self.expr_index), + ExpressionIndex(core.BNGetLowLevelILSSAExprIndex(self.function.handle, self.expr_index)), core.BNGetLowLevelILSSAInstructionIndex(self.function.handle, self.instr_index) if self.instr_index is not None else None) @property @@ -565,7 +565,7 @@ class LowLevelILInstruction(BaseILInstruction): non_ssa_function = self.function.non_ssa_form assert non_ssa_function is not None return LowLevelILInstruction.create(non_ssa_function, - core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index), + ExpressionIndex(core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index)), core.BNGetLowLevelILNonSSAInstructionIndex(self.function.handle, self.instr_index) if self.instr_index is not None else None) @property @@ -666,13 +666,20 @@ class LowLevelILInstruction(BaseILInstruction): result.append(LowLevelILOperationAndSize(self.instr.operation, self.instr.size)) return result - def get_possible_values(self, options:List[DataFlowQueryOption]=[]) -> variable.PossibleValueSet: - option_array = (ctypes.c_int * len(options))() + @staticmethod + def _make_options_array(options:Optional[List[DataFlowQueryOption]]): + if options is None: + options = [] idx = 0 + option_array = (ctypes.c_int * len(options))() for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index, option_array, len(options)) + return option_array, len(options) + + def get_possible_values(self, options:Optional[List[DataFlowQueryOption]]=None) -> variable.PossibleValueSet: + option_array, option_size = LowLevelILInstruction._make_options_array(options) + value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index, option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -691,32 +698,24 @@ class LowLevelILInstruction(BaseILInstruction): value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) return variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) - def get_possible_reg_values(self, reg:'architecture.RegisterType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + def get_possible_reg_values(self, reg:'architecture.RegisterType', options:List[DataFlowQueryOption]=None) -> 'variable.PossibleValueSet': if self.function.arch is None: raise Exception("Can not call get_possible_reg_values on function with Architecture set to None") reg = self.function.arch.get_reg_index(reg) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, option_size = LowLevelILInstruction._make_options_array(options) value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result - def get_possible_reg_values_after(self, reg:'architecture.RegisterType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + def get_possible_reg_values_after(self, reg:'architecture.RegisterType', options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': if self.function.arch is None: raise Exception("Can not call get_possible_reg_values_after on function with Architecture set to None") reg = self.function.arch.get_reg_index(reg) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, option_size = LowLevelILInstruction._make_options_array(options) value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -737,32 +736,24 @@ class LowLevelILInstruction(BaseILInstruction): result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result - def get_possible_flag_values(self, flag:'architecture.FlagType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + def get_possible_flag_values(self, flag:'architecture.FlagType', options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': if self.function.arch is None: raise Exception("Can not call get_possible_flag_values on function with Architecture set to None") flag = self.function.arch.get_flag_index(flag) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, option_size = LowLevelILInstruction._make_options_array(options) value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result - def get_possible_flag_values_after(self, flag:'architecture.FlagType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + def get_possible_flag_values_after(self, flag:'architecture.FlagType', options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': if self.function.arch is None: raise Exception("Can not call get_possible_flag_values_after on function with Architecture set to None") flag = self.function.arch.get_flag_index(flag) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, option_size = LowLevelILInstruction._make_options_array(options) value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -777,26 +768,18 @@ class LowLevelILInstruction(BaseILInstruction): result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result - def get_possible_stack_contents(self, offset:int, size:int, options:List[DataFlowQueryOption]=[]) -> variable.PossibleValueSet: - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + def get_possible_stack_contents(self, offset:int, size:int, options:Optional[List[DataFlowQueryOption]]=None) -> variable.PossibleValueSet: + option_array, option_size = LowLevelILInstruction._make_options_array(options) value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result - def get_possible_stack_contents_after(self, offset:int, size:int, options:List[DataFlowQueryOption]=[]) -> variable.PossibleValueSet: - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + def get_possible_stack_contents_after(self, offset:int, size:int, options:Optional[List[DataFlowQueryOption]]=None) -> variable.PossibleValueSet: + option_array, option_size = LowLevelILInstruction._make_options_array(options) value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -820,12 +803,12 @@ class LowLevelILInstruction(BaseILInstruction): def _get_int(self, operand_index:int) -> int: return (self.instr.operands[operand_index] & ((1 << 63) - 1)) - (self.instr.operands[operand_index] & (1 << 63)) - def _get_target_map(self, operand_index:int) -> Mapping[int, int]: + def _get_target_map(self, operand_index:int) -> Dict[int, int]: count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" try: - value:Mapping[int, int] = {} + value:Dict[int, int] = {} for j in range(count.value // 2): key = operand_list[j * 2] target = operand_list[(j * 2) + 1] @@ -845,11 +828,11 @@ class LowLevelILInstruction(BaseILInstruction): def _get_expr(self, operand_index:int) -> 'LowLevelILInstruction': return LowLevelILInstruction.create(self.function, self.instr.operands[operand_index], self.instr_index) - def _get_reg_stack_adjust(self, operand_index:int) -> Mapping['architecture.RegisterStackName', int]: + def _get_reg_stack_adjust(self, operand_index:int) -> Dict['architecture.RegisterStackName', int]: count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - result:Mapping['architecture.RegisterStackName', int] = {} + result:Dict['architecture.RegisterStackName', int] = {} try: for j in range(count.value // 2): reg_stack = operand_list[j * 2] @@ -1050,22 +1033,22 @@ class LowLevelILConstantBase(LowLevelILInstruction, Constant): def __bool__(self): return self.constant != 0 - def __eq__(self, other): + def __eq__(self, other:'LowLevelILConstantBase'): return self.constant == other.constant - def __ne__(self, other): + def __ne__(self, other:'LowLevelILConstantBase'): return self.constant != other.constant - def __lt__(self, other): + def __lt__(self, other:'LowLevelILConstantBase'): return self.constant < other.constant - def __gt__(self, other): + def __gt__(self, other:'LowLevelILConstantBase'): return self.constant > other.constant - def __le__(self, other): + def __le__(self, other:'LowLevelILConstantBase'): return self.constant <= other.constant - def __ge__(self, other): + def __ge__(self, other:'LowLevelILConstantBase'): return self.constant >= other.constant @property @@ -1911,7 +1894,7 @@ class LowLevelILJumpTo(LowLevelILInstruction): return self._get_expr(0) @property - def targets(self) -> Mapping[int, int]: + def targets(self) -> Dict[int, int]: return self._get_target_map(1) @property @@ -2220,7 +2203,7 @@ class LowLevelILCallStackAdjust(LowLevelILInstruction, Call): return self._get_int(1) @property - def reg_stack_adjustments(self) -> Mapping['architecture.RegisterStackName', int]: + def reg_stack_adjustments(self) -> Dict['architecture.RegisterStackName', int]: return self._get_reg_stack_adjust(2) @property @@ -2503,7 +2486,7 @@ class LowLevelILStoreSsa(LowLevelILInstruction, Store, SSA): return [self.dest, self.dest_memory, self.src_memory, self.src] -ILInstruction:Mapping[LowLevelILOperation, LowLevelILInstruction] = { # type: ignore +ILInstruction:Dict[LowLevelILOperation, LowLevelILInstruction] = { # type: ignore LowLevelILOperation.LLIL_NOP: LowLevelILNop, # [], LowLevelILOperation.LLIL_SET_REG: LowLevelILSetReg, # [("dest", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SPLIT: LowLevelILSetRegSplit, # [("hi", "reg"), ("lo", "reg"), ("src", "expr")], @@ -2754,7 +2737,7 @@ class LowLevelILFunction: raise IndexError("index out of range") if i < 0: i = len(self) + i - return LowLevelILInstruction.create(self, core.BNGetLowLevelILIndexForInstruction(self.handle, i), i) + return LowLevelILInstruction.create(self, ExpressionIndex(core.BNGetLowLevelILIndexForInstruction(self.handle, i)), i) def __setitem__(self, i, j): raise IndexError("instruction modification not implemented") @@ -3210,14 +3193,14 @@ class LowLevelILFunction: """ return self.expr(LowLevelILOperation.LLIL_LOAD, addr, size=size) - def store(self, size:int, addr:ExpressionIndex, value:ExpressionIndex, flags=None) -> ExpressionIndex: + def store(self, size:int, addr:ExpressionIndex, value:ExpressionIndex, flags:Optional['architecture.FlagName']=None) -> ExpressionIndex: """ ``store`` Writes ``size`` bytes to expression ``addr`` read from expression ``value`` :param int size: number of bytes to write :param ExpressionIndex addr: the expression to write to :param ExpressionIndex value: the expression to be written - :param str flags: which flags are set by this operation + :param FlagName flags: which flags are set by this operation :return: The expression ``[addr].size = value`` :rtype: ExpressionIndex """ @@ -3884,11 +3867,11 @@ class LowLevelILFunction: class_index = self.arch.get_semantic_flag_class_index(sem_class) return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond, architecture.SemanticClassIndex(class_index)) - def flag_group(self, sem_group) -> ExpressionIndex: + def flag_group(self, sem_group:'architecture.SemanticGroupName') -> ExpressionIndex: """ ``flag_group`` returns a flag_group expression for the given semantic flag group - :param str sem_group: Semantic flag group to access + :param SemanticGroupName sem_group: Semantic flag group to access :return: A flag_group expression :rtype: ExpressionIndex """ @@ -4414,7 +4397,7 @@ class LowLevelILFunction: """ core.BNLowLevelILMarkLabel(self.handle, label.handle) - def add_label_map(self, labels:Mapping[int, LowLevelILLabel]) -> ExpressionIndex: + def add_label_map(self, labels:Dict[int, LowLevelILLabel]) -> ExpressionIndex: """ ``add_label_map`` returns a label list expression for the given list of LowLevelILLabel objects. diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 9381a5d3..5c960383 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -338,7 +338,7 @@ class MediumLevelILInstruction(BaseILInstruction): ssa_func = self.function.ssa_form assert ssa_func is not None return MediumLevelILInstruction.create(ssa_func, - core.BNGetMediumLevelILSSAExprIndex(self.function.handle, self.expr_index)) + ExpressionIndex(core.BNGetMediumLevelILSSAExprIndex(self.function.handle, self.expr_index))) @property def non_ssa_form(self) -> 'MediumLevelILInstruction': @@ -346,7 +346,7 @@ class MediumLevelILInstruction(BaseILInstruction): non_ssa_func = self.function.non_ssa_form assert non_ssa_func is not None return MediumLevelILInstruction.create(non_ssa_func, - core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) + ExpressionIndex(core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle, self.expr_index))) @property def value(self) -> variable.RegisterValue: @@ -493,26 +493,29 @@ class MediumLevelILInstruction(BaseILInstruction): return types.Type.create(core.BNNewTypeReference(result.type), platform = platform, confidence = result.confidence) return None - def get_possible_values(self, options:List[DataFlowQueryOption]=[]) -> variable.PossibleValueSet: - option_array = (ctypes.c_int * len(options))() + @staticmethod + def _make_options_array(options:Optional[List[DataFlowQueryOption]]): + if options is None: + options = [] idx = 0 + option_array = (ctypes.c_int * len(options))() for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index, option_array, len(options)) + return option_array, len(options) + + def get_possible_values(self, options:Optional[List[DataFlowQueryOption]]=None) -> variable.PossibleValueSet: + option_array, size = MediumLevelILInstruction._make_options_array(options) + value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index, option_array, size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_ssa_var_possible_values(self, ssa_var:SSAVariable, options:List[DataFlowQueryOption]=[]): var_data = ssa_var.var.to_BNVariable() - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, size = MediumLevelILInstruction._make_options_array(options) value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, - self.instr_index, option_array, len(options)) + self.instr_index, option_array, size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -548,29 +551,21 @@ class MediumLevelILInstruction(BaseILInstruction): return result def get_possible_reg_values(self, reg:'architecture.RegisterType', - options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': + option_array, size = MediumLevelILInstruction._make_options_array(options) reg = self.function.arch.get_reg_index(reg) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index, - option_array, len(options)) + option_array, size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg:'architecture.RegisterType', - options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': reg = self.function.arch.get_reg_index(reg) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, size = MediumLevelILInstruction._make_options_array(options) value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index, - option_array, len(options)) + option_array, size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -588,29 +583,21 @@ class MediumLevelILInstruction(BaseILInstruction): return result def get_possible_flag_values(self, flag:'architecture.FlagType', - options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': flag = self.function.arch.get_flag_index(flag) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, size = MediumLevelILInstruction._make_options_array(options) value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index, - option_array, len(options)) + option_array, size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag:'architecture.FlagType', - options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': + options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': flag = self.function.arch.get_flag_index(flag) - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + option_array, size = MediumLevelILInstruction._make_options_array(options) value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index, - option_array, len(options)) + option_array, size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -626,27 +613,19 @@ class MediumLevelILInstruction(BaseILInstruction): return result def get_possible_stack_contents(self, offset:int, size:int, - options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + options:Optional[List[DataFlowQueryOption]]=None) -> 'variable.PossibleValueSet': + option_array, option_size = MediumLevelILInstruction._make_options_array(options) value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_stack_contents_after(self, offset:int, size:int, - options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - option_array = (ctypes.c_int * len(options))() - idx = 0 - for option in options: - option_array[idx] = option - idx += 1 + options:List[DataFlowQueryOption]=None) -> 'variable.PossibleValueSet': + option_array, option_size = MediumLevelILInstruction._make_options_array(options) value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index, - option_array, len(options)) + option_array, option_size) result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -723,6 +702,11 @@ class MediumLevelILInstruction(BaseILInstruction): core.BNMediumLevelILFreeOperandList(operand_list) def _get_var_list(self, operand_index1:int, operand_index2:int) -> List[variable.Variable]: + # We keep this extra parameter around because when this function is called + # the subclasses that call this don't use the next operand + # without this parameter it looks like this operand is being skipped unintentionally + # rather this operand is being skipped intentionally. + _ = operand_index2 count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" @@ -765,7 +749,7 @@ class MediumLevelILInstruction(BaseILInstruction): count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" - value:Mapping[int, int] = {} + value:Dict[int, int] = {} try: for j in range(count.value // 2): key = operand_list[j * 2] @@ -2333,7 +2317,7 @@ class MediumLevelILTailcallUntypedSsa(MediumLevelILCallBase, Tailcall, SSA): return self._get_expr(1) @property - def params(self) -> MediumLevelILInstruction: + def params(self) -> List[SSAVariable]: inst = self._get_expr(2) assert isinstance(inst, MediumLevelILCallParamSsa), "MediumLevelILTailcallUntypedSsa return bad type for 'params'" return inst.src @@ -2645,7 +2629,7 @@ class MediumLevelILFunction: raise IndexError("index out of range") if i < 0: i = len(self) + i - return MediumLevelILInstruction.create(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) + return MediumLevelILInstruction.create(self, ExpressionIndex(core.BNGetMediumLevelILIndexForInstruction(self.handle, i)), i) def __setitem__(self, i, j): raise IndexError("instruction modification not implemented") @@ -2684,7 +2668,7 @@ class MediumLevelILFunction: count = ctypes.c_ulonglong() blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) assert blocks is not None, "core.BNGetMediumLevelILBasicBlockList returned None" - return (count, blocks) + return count, blocks def _instantiate_block(self, handle): return MediumLevelILBasicBlock(handle, self, self.view) @@ -2842,10 +2826,10 @@ class MediumLevelILFunction: core.BNFinalizeMediumLevelILFunction(self.handle) def get_ssa_instruction_index(self, instr:InstructionIndex) -> InstructionIndex: - return core.BNGetMediumLevelILSSAInstructionIndex(self.handle, instr) + return InstructionIndex(core.BNGetMediumLevelILSSAInstructionIndex(self.handle, instr)) def get_non_ssa_instruction_index(self, instr:InstructionIndex) -> InstructionIndex: - return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr) + return InstructionIndex(core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr)) def get_ssa_var_definition(self, ssa_var:SSAVariable) -> Optional[MediumLevelILInstruction]: var_data = ssa_var.var.to_BNVariable() @@ -2932,7 +2916,7 @@ class MediumLevelILFunction: result = core.BNGetLowLevelILInstructionIndex(self.handle, instr) if result >= core.BNGetLowLevelILInstructionCount(low_il.handle): return None - return result + return lowlevelil.InstructionIndex(result) def get_low_level_il_expr_index(self, expr:ExpressionIndex) -> Optional['lowlevelil.ExpressionIndex']: low_il = self.low_level_il @@ -2944,15 +2928,15 @@ class MediumLevelILFunction: result = core.BNGetLowLevelILExprIndex(self.handle, expr) if result >= core.BNGetLowLevelILExprCount(low_il.handle): return None - return result + return lowlevelil.ExpressionIndex(result) def get_low_level_il_expr_indexes(self, expr:ExpressionIndex) -> List['lowlevelil.ExpressionIndex']: count = ctypes.c_ulonglong() exprs = core.BNGetLowLevelILExprIndexes(self.handle, expr, count) assert exprs is not None, "core.BNGetLowLevelILExprIndexes returned None" - result = [] + result:List['lowlevelil.ExpressionIndex'] = [] for i in range(0, count.value): - result.append(exprs[i]) + result.append(lowlevelil.ExpressionIndex(exprs[i])) core.BNFreeILInstructionList(exprs) return result @@ -2963,7 +2947,7 @@ class MediumLevelILFunction: result = core.BNGetHighLevelILInstructionIndex(self.handle, instr) if result >= core.BNGetHighLevelILInstructionCount(high_il.handle): return None - return result + return highlevelil.InstructionIndex(result) def get_high_level_il_expr_index(self, expr:ExpressionIndex) -> Optional['highlevelil.ExpressionIndex']: high_il = self.high_level_il @@ -2972,15 +2956,15 @@ class MediumLevelILFunction: result = core.BNGetHighLevelILExprIndex(self.handle, expr) if result >= core.BNGetHighLevelILExprCount(high_il.handle): return None - return result + return highlevelil.ExpressionIndex(result) def get_high_level_il_expr_indexes(self, expr:ExpressionIndex) -> List['highlevelil.ExpressionIndex']: count = ctypes.c_ulonglong() exprs = core.BNGetHighLevelILExprIndexes(self.handle, expr, count) assert exprs is not None, "core.BNGetHighLevelILExprIndexes returned None" - result = [] + result:List['highlevelil.ExpressionIndex'] = [] for i in range(0, count.value): - result.append(exprs[i]) + result.append(highlevelil.ExpressionIndex(exprs[i])) core.BNFreeILInstructionList(exprs) return result @@ -3117,7 +3101,7 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock): def __contains__(self, instruction): if type(instruction) != MediumLevelILInstruction or instruction.il_basic_block != self: return False - if instruction.instr_index >= self.start and instruction.instr_index <= self.end: + if self.start <= instruction.instr_index <= self.end: return True else: return False diff --git a/python/platform.py b/python/platform.py index 84125456..050aa21e 100644 --- a/python/platform.py +++ b/python/platform.py @@ -20,7 +20,7 @@ import os import ctypes -from typing import Mapping, Optional, List +from typing import List, Dict, Optional # Binary Ninja components import binaryninja @@ -390,7 +390,7 @@ class Platform(metaclass=_PlatformMetaClass): def get_auto_platform_type_id_source(self): return core.BNGetAutoPlatformTypeIdSource(self.handle) - def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): + def parse_types_from_source(self, source, filename=None, include_dirs:Optional[List[str]]=None, auto_type_source=None): """ ``parse_types_from_source`` parses the source string and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. @@ -414,6 +414,8 @@ class Platform(metaclass=_PlatformMetaClass): filename = "input" if not isinstance(source, str): raise AttributeError("Source must be a string") + if include_dirs is None: + include_dirs = [] dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): dir_buf[i] = include_dirs[i].encode('charmap') @@ -426,9 +428,9 @@ class Platform(metaclass=_PlatformMetaClass): core.free_string(errors) if not result: raise SyntaxError(error_str) - type_dict:Mapping[types.QualifiedName, types.Type] = {} - variables:Mapping[types.QualifiedName, types.Type] = {} - functions:Mapping[types.QualifiedName, types.Type] = {} + type_dict:Dict[types.QualifiedName, types.Type] = {} + variables:Dict[types.QualifiedName, types.Type] = {} + functions:Dict[types.QualifiedName, types.Type] = {} for i in range(0, parse.typeCount): name = types.QualifiedName._from_core_struct(parse.types[i].name) type_dict[name] = types.Type.create(core.BNNewTypeReference(parse.types[i].type), platform = self) @@ -441,7 +443,7 @@ class Platform(metaclass=_PlatformMetaClass): core.BNFreeTypeParserResult(parse) return types.TypeParserResult(type_dict, variables, functions) - def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): + def parse_types_from_source_file(self, filename, include_dirs:Optional[List[str]]=None, auto_type_source=None): """ ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. @@ -463,7 +465,9 @@ class Platform(metaclass=_PlatformMetaClass): >>> """ if not (isinstance(filename, str) and os.path.isfile(filename) and os.access(filename, os.R_OK)): - raise AttributeError("File {} doesn't exist or isn't readable".format(filename)) + raise AttributeError("File {} doesn't exist or isn't readable".format(filename)) + if include_dirs is None: + include_dirs = [] dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): dir_buf[i] = include_dirs[i].encode('charmap') diff --git a/python/types.py b/python/types.py index 296380ee..c5086d56 100644 --- a/python/types.py +++ b/python/types.py @@ -238,12 +238,12 @@ class CoreSymbol: @property def type(self) -> SymbolType: """Symbol type (read-only)""" - return SymbolType(core.BNGetSymbolType(self._handle).value) + return SymbolType(core.BNGetSymbolType(self._handle)) @property def binding(self) -> SymbolBinding: """Symbol binding (read-only)""" - return SymbolBinding(core.BNGetSymbolBinding(self._handle).value) + return SymbolBinding(core.BNGetSymbolBinding(self._handle)) @property def namespace(self) -> 'NameSpace': @@ -753,7 +753,7 @@ class TypeBuilder: @property def type_class(self) -> TypeClass: - return TypeClass(core.BNGetTypeBuilderClass(self._handle).value) + return TypeClass(core.BNGetTypeBuilderClass(self._handle)) @property def signed(self) -> BoolWithConfidence: @@ -1100,7 +1100,7 @@ class StructureBuilder(TypeBuilder): @property def type(self) -> StructureVariant: - return StructureVariant(core.BNGetStructureBuilderType(self.builder_handle).value) + return StructureVariant(core.BNGetStructureBuilderType(self.builder_handle)) @type.setter def type(self, value:StructureVariant) -> None: @@ -1389,7 +1389,7 @@ class NamedTypeReferenceBuilder(TypeBuilder): @property def named_type_class(self) -> NamedTypeReferenceClass: - return NamedTypeReferenceClass(core.BNGetTypeReferenceBuilderClass(self.ntr_builder_handle).value) + return NamedTypeReferenceClass(core.BNGetTypeReferenceBuilderClass(self.ntr_builder_handle)) @staticmethod def named_type(named_type:'NamedTypeReferenceBuilder', width:int=0, align:int=1, @@ -1462,7 +1462,7 @@ class Type: def create(cls, handle=core.BNTypeHandle, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'Type': assert handle is not None, "Passed a handle which is None" assert isinstance(handle, core.BNTypeHandle) - type_class = TypeClass(core.BNGetTypeClass(handle).value) + type_class = TypeClass(core.BNGetTypeClass(handle)) return Types[type_class](handle, platform, confidence) def __del__(self): @@ -1500,7 +1500,7 @@ class Type: @property def type_class(self) -> TypeClass: """Type class (read-only)""" - return TypeClass(core.BNGetTypeClass(self._handle).value) + return TypeClass(core.BNGetTypeClass(self._handle)) @property def width(self) -> int: @@ -2003,7 +2003,7 @@ class StructureType(Type): @property def type(self) -> StructureVariant: - return StructureVariant(core.BNGetStructureType(self.struct_handle).value) + return StructureVariant(core.BNGetStructureType(self.struct_handle)) def with_replaced_structure(self, from_struct, to_struct) -> 'StructureType': return StructureType(core.BNStructureWithReplacedStructure(self.struct_handle, from_struct.handle, to_struct.handle)) @@ -2099,7 +2099,7 @@ class EnumerationType(IntegerType): class PointerType(Type): @property def ref_type(self) -> ReferenceType: - return ReferenceType(core.BNTypeGetReferenceType(self._handle).value) + return ReferenceType(core.BNTypeGetReferenceType(self._handle)) @classmethod def create(cls, arch:'architecture.Architecture', type:SomeType, const:BoolWithConfidenceType=False, @@ -2297,7 +2297,7 @@ class NamedTypeReferenceType(Type): _guid = str(uuid.uuid4()) if type is None: - return cls.create(NamedTypeReferenceClass.UnknownNamedTypeClass, _guid, name) + return cls.create(NamedTypeReferenceClass.UnknownNamedTypeClass, _guid, name, 0, 0, platform, confidence) else: return type.generate_named_type_reference(_guid, name) @@ -2337,7 +2337,7 @@ class NamedTypeReferenceType(Type): @property def named_type_class(self) -> NamedTypeReferenceClass: - return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.ntr_handle).value) + return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.ntr_handle)) @property def type_id(self) -> str: @@ -2476,8 +2476,8 @@ def preprocess_source(source:str, filename:str=None, include_dirs:Optional[List[ core.free_string(output) core.free_string(errors) if result: - return (output_str, error_str) - return (None, error_str) + return output_str, error_str + return None, error_str @dataclass(frozen=True) diff --git a/python/variable.py b/python/variable.py index d7e46510..f6470429 100644 --- a/python/variable.py +++ b/python/variable.py @@ -21,7 +21,7 @@ import ctypes from typing import List, Generator, Optional, Union, Set, Mapping -from dataclasses import dataclass, field +from dataclasses import dataclass import binaryninja from . import _binaryninjacore as core @@ -38,13 +38,11 @@ FunctionOrILFunction = Union["binaryninja.function.Function", class LookupTableEntry: from_values:List[int] to_value:int + type:RegisterValueType = RegisterValueType.LookupTableValue def __repr__(self): return f"[{', '.join([f'{i:#x}' for i in self.from_values])}] -> {self.to_value:#x}" - def type(self): - return RegisterValueType.LookupTableValue - @dataclass(frozen=True) class RegisterValue: @@ -463,7 +461,7 @@ class PossibleValueSet: """ Create a PossibleValueSet object for a stack frame offset. - :param int value: Integer value of the offset + :param int offset: Integer value of the offset :rtype: PossibleValueSet """ result = PossibleValueSet() @@ -733,7 +731,6 @@ class Variable(CoreVariable): raise NotImplementedError("No IL function associated with variable") version_count = ctypes.c_ulonglong() - versions = None if self._il_function.il_form in [FunctionGraphType.MediumLevelILFunctionGraph, FunctionGraphType.MediumLevelILSSAFormFunctionGraph]: versions = core.BNGetMediumLevelILVariableSSAVersions(self._il_function.handle, self.to_BNVariable(), version_count) elif self._il_function.il_form in [FunctionGraphType.HighLevelILFunctionGraph, FunctionGraphType.HighLevelILSSAFormFunctionGraph]: @@ -758,6 +755,10 @@ class Variable(CoreVariable): def dead_store_elimination(self, value): core.BNSetFunctionVariableDeadStoreElimination(self._function.handle, self.to_BNVariable(), value) + @property + def function(self) -> 'binaryninja.function.Function': + """returns the source Function object which this variable belongs to""" + return self._function @dataclass(frozen=True) class ConstantReference: @@ -836,4 +837,4 @@ class AddressRange: return f"<{self.start:#x}-{self.end:#x}>" def __contains__(self, i:int): - return i >= self.start and i < self.end
\ No newline at end of file + return self.start <= i < self.end
\ No newline at end of file |
