diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0471c11..accad7f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,31 +14,4 @@ jobs: uses: ./.github/workflows/windows.yml macos: uses: ./.github/workflows/macos.yml - docs: - runs-on: ubuntu-22.04 - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - submodules: true - - name: Setup python - uses: actions/setup-python@v4 - with: - python-version: 3.8 - - name: Install - run: | - pip install -U pip - pip install git+https://github.com/angr/archinfo.git - pip install .[docs] - - name: Build docs - run: cd docs && make html - - name: Build coverage - run: cd docs && make coverage - - name: Test coverage - run: | - if [ -s docs/_build/coverage/python.txt ]; then - echo "Doc coverage is missing for the for:" - cat docs/_build/coverage/python.txt - exit 1 - fi diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 1ed7e768..f8ef2308 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -1,10 +1,10 @@ name: OSS-Fuzz on: - push: - branches: - - master - pull_request: + # push: + # branches: + # - master + # pull_request: workflow_dispatch: permissions: {} diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 900c5718..e3a7a4b3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -19,7 +19,7 @@ jobs: path: binaries - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.10" - run: python -m venv $HOME/venv name: Create venv shell: bash diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 6f197bf9..e9bdc630 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -19,7 +19,7 @@ jobs: path: binaries - uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.10" - run: python -m venv $HOME/venv name: Create venv shell: bash diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fb8043bd..dd237862 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -63,7 +63,7 @@ repos: rev: v3.15.2 hooks: - id: pyupgrade - args: [--py38-plus] + args: [--py310-plus] - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.4.3 diff --git a/.readthedocs.yml b/.readthedocs.yml index b46c01b0..a2836ba6 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,7 +9,7 @@ submodules: build: os: ubuntu-22.04 tools: - python: "3.8" + python: "3.10" jobs: pre_install: - pip install -U pip diff --git a/pyproject.toml b/pyproject.toml index 1413f480..576beb2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [tool.black] line-length = 120 -target-version = ['py38'] +target-version = ['py310'] force-exclude = ''' /( vex diff --git a/pyvex/arches.py b/pyvex/arches.py index 9ac8b466..79bf50e5 100644 --- a/pyvex/arches.py +++ b/pyvex/arches.py @@ -1,5 +1,3 @@ -from typing import Dict, List, Tuple - from ._register_info import REGISTER_OFFSETS from .enums import default_vex_archinfo, vex_endness_from_string from .types import Register @@ -17,8 +15,8 @@ def __init__(self, name: str, bits: int, memory_endness: str, instruction_endnes self.memory_endness = memory_endness self.instruction_endness = instruction_endness self.byte_width = 8 - self.register_list: List[Register] = [] - self.registers: Dict[str, Tuple[int, int]] = {} + self.register_list: list[Register] = [] + self.registers: dict[str, tuple[int, int]] = {} self.vex_arch = { "X86": "VexArchX86", "AMD64": "VexArchAMD64", diff --git a/pyvex/block.py b/pyvex/block.py index 01d4bb4f..ac996f33 100644 --- a/pyvex/block.py +++ b/pyvex/block.py @@ -1,7 +1,7 @@ import copy import itertools import logging -from typing import List, Optional, Tuple +from typing import Optional from . import expr, stmt from .const import get_type_size @@ -125,17 +125,17 @@ def __init__( self.addr = mem_addr self.arch: Arch = arch - self.statements: List[IRStmt] = [] - self.next: Optional[IRExpr] = None + self.statements: list[IRStmt] = [] + self.next: IRExpr | None = None self._tyenv: Optional["IRTypeEnv"] = None - self.jumpkind: Optional[str] = None - self._direct_next: Optional[bool] = None - self._size: Optional[int] = None - self._instructions: Optional[int] = None - self._exit_statements: Optional[Tuple[Tuple[int, int, IRStmt], ...]] = None + self.jumpkind: str | None = None + self._direct_next: bool | None = None + self._size: int | None = None + self._instructions: int | None = None + self._exit_statements: tuple[tuple[int, int, IRStmt], ...] | None = None self.default_exit_target = None self.data_refs = () - self._instruction_addresses: Tuple[int, ...] = () + self._instruction_addresses: tuple[int, ...] = () if data is not None: # This is the slower path (because we need to call _from_py() to copy the content in the returned IRSB to @@ -180,7 +180,7 @@ def has_statements(self) -> bool: return self.statements is not None and bool(self.statements) @property - def exit_statements(self) -> Tuple[Tuple[int, int, IRStmt], ...]: + def exit_statements(self) -> tuple[tuple[int, int, IRStmt], ...]: if self._exit_statements is not None: return self._exit_statements @@ -409,7 +409,7 @@ def instructions(self): return self._instructions @property - def instruction_addresses(self) -> Tuple[int, ...]: + def instruction_addresses(self) -> tuple[int, ...]: """ Addresses of instructions in this block. """ diff --git a/pyvex/const.py b/pyvex/const.py index ef665f77..7b00826a 100644 --- a/pyvex/const.py +++ b/pyvex/const.py @@ -1,5 +1,4 @@ import re -from typing import List, Optional from .enums import VEXObject, get_enum_from_int from .errors import PyVEXError @@ -11,7 +10,7 @@ class IRConst(VEXObject): __slots__ = ["_value"] type: str - size: Optional[int] = None + size: int | None = None tag: str c_constructor = None _value: int @@ -58,7 +57,7 @@ def __hash__(self): class U1(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_I1" size = 1 @@ -78,7 +77,7 @@ def _from_c(c_const): class U8(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_I8" size = 8 @@ -101,7 +100,7 @@ def _from_c(c_const): class U16(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_I16" size = 16 @@ -129,7 +128,7 @@ def _from_c(c_const): class U32(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_I32" size = 32 @@ -157,7 +156,7 @@ def _from_c(c_const): class U64(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_I64" size = 64 @@ -210,7 +209,7 @@ def __str__(self): class F32(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_F32" tag = "Ico_F32" @@ -229,7 +228,7 @@ def _from_c(c_const): class F32i(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_F32" tag = "Ico_F32i" @@ -248,7 +247,7 @@ def _from_c(c_const): class F64(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_F64" tag = "Ico_F64" @@ -267,7 +266,7 @@ def _from_c(c_const): class F64i(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_F64" tag = "Ico_F64i" @@ -286,7 +285,7 @@ def _from_c(c_const): class V128(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_V128" tag = "Ico_V128" @@ -312,7 +311,7 @@ def _from_c(c_const): class V256(IRConst): - __slots__: List[str] = [] + __slots__: list[str] = [] type = "Ity_V256" tag = "Ico_V256" diff --git a/pyvex/enums.py b/pyvex/enums.py index e669b8fb..ca5be8c1 100644 --- a/pyvex/enums.py +++ b/pyvex/enums.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List +from typing import Any from .native import ffi, pvc from .utils import stable_hash @@ -9,7 +9,7 @@ class VEXObject: The base class for Vex types. """ - __slots__: List[str] = [] + __slots__: list[str] = [] def __eq__(self, other): if not isinstance(other, type(self)): @@ -95,9 +95,9 @@ def _to_c(arr): return pvc.mkIRRegArray(arr.base, get_int_from_enum(arr.elemTy), arr.nElems) -ints_to_enums: Dict[int, str] = {} -enums_to_ints: Dict[str, int] = {} -irop_enums_to_ints: Dict[str, int] = {} +ints_to_enums: dict[int, str] = {} +enums_to_ints: dict[str, int] = {} +irop_enums_to_ints: dict[str, int] = {} will_be_overwritten = ["Ircr_GT", "Ircr_LT"] @@ -137,7 +137,7 @@ def vex_endness_from_string(endness_str): return getattr(pvc, endness_str) -def default_vex_archinfo() -> Dict[str, Any]: +def default_vex_archinfo() -> dict[str, Any]: return { "hwcaps": 0, "endness": vex_endness_from_string("VexEndnessLE"), diff --git a/pyvex/expr.py b/pyvex/expr.py index 1f9eed42..1a1b399f 100644 --- a/pyvex/expr.py +++ b/pyvex/expr.py @@ -1,6 +1,6 @@ import logging import re -from typing import Dict, List, Optional, Tuple +from typing import Optional from .const import U8, U16, U32, U64, IRConst, get_type_size from .enums import IRCallee, IRRegArray, VEXObject, get_enum_from_int, get_int_from_enum @@ -17,7 +17,7 @@ class IRExpr(VEXObject): __slots__ = [] - tag: Optional[str] = None + tag: str | None = None tag_int = 0 # set automatically at bottom of file def pp(self): @@ -30,7 +30,7 @@ def _pp_str(self) -> str: raise NotImplementedError @property - def child_expressions(self) -> List["IRExpr"]: + def child_expressions(self) -> list["IRExpr"]: """ A list of all of the expressions that this expression ends up evaluating. """ @@ -282,7 +282,7 @@ class Get(IRExpr): tag = "Iex_Get" - def __init__(self, offset, ty: str, ty_int: Optional[int] = None): + def __init__(self, offset, ty: str, ty_int: int | None = None): self.offset = offset if ty_int is None: self.ty_int = get_int_from_enum(ty) @@ -762,7 +762,7 @@ def get_op_retty(op): return op_arg_types(op)[0] -op_signatures: Dict[str, Tuple[str, Tuple[str, ...]]] = {} +op_signatures: dict[str, tuple[str, tuple[str, ...]]] = {} def _request_op_type_from_cache(op): diff --git a/pyvex/lifting/lift_function.py b/pyvex/lifting/lift_function.py index a14dd8bd..446b2112 100644 --- a/pyvex/lifting/lift_function.py +++ b/pyvex/lifting/lift_function.py @@ -1,6 +1,6 @@ import logging from collections import defaultdict -from typing import DefaultDict, List, Optional, Type +from typing import DefaultDict from pyvex import const from pyvex.block import IRSB @@ -15,8 +15,8 @@ log = logging.getLogger(__name__) -lifters: DefaultDict[str, List[Type[Lifter]]] = defaultdict(list) -postprocessors: DefaultDict[str, List[Type[Postprocessor]]] = defaultdict(list) +lifters: DefaultDict[str, list[type[Lifter]]] = defaultdict(list) +postprocessors: DefaultDict[str, list[type[Postprocessor]]] = defaultdict(list) def lift( @@ -74,7 +74,7 @@ def lift( if isinstance(data, str): raise TypeError("Cannot pass unicode string as data to lifter") - py_data: Optional[PyLiftSource] + py_data: PyLiftSource | None if isinstance(data, (bytes, bytearray, memoryview)): py_data = data c_data = None diff --git a/pyvex/lifting/lifter.py b/pyvex/lifting/lifter.py index d60e0612..410a1948 100644 --- a/pyvex/lifting/lifter.py +++ b/pyvex/lifting/lifter.py @@ -1,5 +1,3 @@ -from typing import Optional, Union - from pyvex.block import IRSB from pyvex.types import Arch, LiftSource @@ -54,13 +52,13 @@ def __init__(self, arch: Arch, addr: int): def lift( self, data: LiftSource, - bytes_offset: Optional[int] = None, - max_bytes: Optional[int] = None, - max_inst: Optional[int] = None, - opt_level: Union[int, float] = 1, - traceflags: Optional[int] = None, - allow_arch_optimizations: Optional[bool] = None, - strict_block_end: Optional[bool] = None, + bytes_offset: int | None = None, + max_bytes: int | None = None, + max_inst: int | None = None, + opt_level: int | float = 1, + traceflags: int | None = None, + allow_arch_optimizations: bool | None = None, + strict_block_end: bool | None = None, skip_stmts: bool = False, collect_data_refs: bool = False, cross_insn_opt: bool = True, diff --git a/pyvex/lifting/util/instr_helper.py b/pyvex/lifting/util/instr_helper.py index 8129e74a..bdef5b15 100644 --- a/pyvex/lifting/util/instr_helper.py +++ b/pyvex/lifting/util/instr_helper.py @@ -1,6 +1,5 @@ import abc import string -from typing import Dict import bitstring @@ -68,7 +67,7 @@ class Instruction(metaclass=abc.ABCMeta): See the examples provided by gymrat for ideas of how to use this to build your own lifters quickly and easily. """ - data: Dict[str, str] + data: dict[str, str] irsb_c: IRSBCustomizer def __init__(self, bitstrm, arch, addr): diff --git a/pyvex/lifting/util/lifter_helper.py b/pyvex/lifting/util/lifter_helper.py index e9fc9877..3140abbe 100644 --- a/pyvex/lifting/util/lifter_helper.py +++ b/pyvex/lifting/util/lifter_helper.py @@ -1,5 +1,5 @@ import logging -from typing import TYPE_CHECKING, List, Type +from typing import TYPE_CHECKING import bitstring @@ -46,7 +46,7 @@ class GymratLifter(Lifter): ) REQUIRE_DATA_PY = True - instrs: List[Type["Instruction"]] + instrs: list[type["Instruction"]] def __init__(self, arch, addr): super().__init__(arch, addr) diff --git a/pyvex/stmt.py b/pyvex/stmt.py index b66d94cd..1e5f02dc 100644 --- a/pyvex/stmt.py +++ b/pyvex/stmt.py @@ -1,5 +1,5 @@ import logging -from typing import Iterator, Optional +from collections.abc import Iterator from . import expr from .const import IRConst @@ -16,7 +16,7 @@ class IRStmt(VEXObject): IR statements in VEX represents operations with side-effects. """ - tag: Optional[str] = None + tag: str | None = None tag_int = 0 # set automatically at bottom of file __slots__ = [] diff --git a/pyvex/types.py b/pyvex/types.py index 09331f7c..feb3b7f3 100644 --- a/pyvex/types.py +++ b/pyvex/types.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Protocol, Tuple, Union, runtime_checkable +from typing import TYPE_CHECKING, Any, Protocol, Union, runtime_checkable from cffi.api import FFI @@ -22,10 +22,10 @@ class Arch(Protocol): instruction_endness: str memory_endness: str byte_width: int - register_list: List[Register] - registers: Dict[str, Tuple[int, int]] + register_list: list[Register] + registers: dict[str, tuple[int, int]] - def translate_register_name(self, offset: int, size: Optional[int] = None) -> Optional[str]: ... + def translate_register_name(self, offset: int, size: int | None = None) -> str | None: ... def get_register_offset(self, name: str) -> int: ... @@ -37,7 +37,7 @@ class LibvexArch(Protocol): """ vex_arch: str - vex_archinfo: Dict[str, Any] + vex_archinfo: dict[str, Any] PyLiftSource = Union[bytes, bytearray, memoryview] diff --git a/pyvex/utils.py b/pyvex/utils.py index 17129d1b..ec4334be 100644 --- a/pyvex/utils.py +++ b/pyvex/utils.py @@ -1,5 +1,6 @@ import struct -from typing import Any, Callable, Dict, Tuple +from collections.abc import Callable +from typing import Any try: import _md5 as md5lib @@ -10,13 +11,13 @@ md5_unpacker = struct.Struct("4I") -def stable_hash(t: Tuple) -> int: +def stable_hash(t: tuple) -> int: cnt = _dump_tuple(t) hd = md5lib.md5(cnt).digest() return md5_unpacker.unpack(hd)[0] # 32 bits -def _dump_tuple(t: Tuple) -> bytes: +def _dump_tuple(t: tuple) -> bytes: cnt = b"" for item in t: if item is not None: @@ -54,7 +55,7 @@ def _dump_type(t: type) -> bytes: return t.__name__.encode("ascii") -_DUMP_BY_TYPE: Dict[type, Callable[[Any], bytes]] = { +_DUMP_BY_TYPE: dict[type, Callable[[Any], bytes]] = { tuple: _dump_tuple, str: _dump_str, int: _dump_int, diff --git a/setup.cfg b/setup.cfg index fefe52e8..47c0fd9b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,8 +13,6 @@ classifiers = License :: OSI Approved :: BSD License Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 @@ -24,7 +22,7 @@ packages = find: install_requires = bitstring cffi>=1.0.3;implementation_name == 'cpython' -python_requires = >=3.8 +python_requires = >=3.10 include_package_data = True [options.extras_require]