Skip to content

Instantly share code, notes, and snippets.

@mincrmatt12
Created October 19, 2021 19:20
Show Gist options
  • Save mincrmatt12/bfaf52556c8195e75e0c934fc851f36f to your computer and use it in GitHub Desktop.
Save mincrmatt12/bfaf52556c8195e75e0c934fc851f36f to your computer and use it in GitHub Desktop.
evil bytecode hackery in python pt1: getting around libraries that require positional arguments
import dis
import types
_INSN = type("INSN", (), {x: (lambda arg=0, y=y: bytes((y, arg))) for x, y in dis.opmap.items()})
_CFN = {y: x for x, y in dis.COMPILER_FLAG_NAMES.items()}
def build_proxy_to(fn, nargs):
"""
Do evil magic to build a function object of signature fn(x0, x1, ..., xnargs) which calls fn(*x)
"""
# Build bytecode:
code = _INSN.LOAD_CONST(0) # load ref to fn
for i in range(nargs):
code += _INSN.LOAD_FAST(i) # load nth argument from locals (first args locals are args)
code += _INSN.CALL_FUNCTION(nargs) + _INSN.RETURN_VALUE()
# Generate code object
co_obj = types.CodeType(
nargs, 0, 0, nargs, nargs + 1, _CFN["NOFREE"] | _CFN["OPTIMIZED"] | _CFN["NEWLOCALS"],
code, (fn,), (), tuple([f"x{i}" for i in range(nargs)]), "<build_proxy>", fn.__code__.co_name + f"_p{nargs}",
1, b"\x00\x01", (), ()
)
# Create function object
return types.FunctionType(co_obj, globals(), co_obj.co_name, None, None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment