Compare commits

...
31 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås 418c5e3f43 subprojects: Prepare for release 2026-10-08 14:49:02 +02:00
Ole André Vadla Ravnås a1929a4dc5 subprojects: Bump outdated 2026-10-08 14:32:45 +02:00
Ole André Vadla Ravnås aacd1913e0 subprojects: Prepare for release 2026-10-07 14:27:03 +02:00
Ole André Vadla Ravnås ea6c66da96 subprojects: Bump outdated 2026-10-07 14:24:00 +02:00
Ole André Vadla Ravnås 57b6cbae38 submodules: Bump releng 2026-10-07 14:24:00 +02:00
Ole André Vadla Ravnås 1b18f0174d subprojects: Prepare for release 2026-10-05 10:00:33 +02:00
Ole André Vadla Ravnås 7f04d40687 subprojects: Bump outdated 2026-10-05 09:57:11 +02:00
Ole André Vadla Ravnås c69db7eb40 submodules: Bump releng 2026-10-05 09:57:10 +02:00
Ole André Vadla Ravnås ce49a3102a subprojects: Prepare for release 2026-10-04 11:35:34 +02:00
Ole André Vadla Ravnås 288133374a subprojects: Bump outdated 2026-10-04 11:34:54 +02:00
Ole André Vadla Ravnås 56843bb3f8 subprojects: Prepare for release 2026-10-03 07:56:17 +02:00
Ole André Vadla Ravnås d90f991948 subprojects: Bump outdated 2026-10-03 07:55:28 +02:00
Ole André Vadla Ravnås c744c2a12a subprojects: Prepare for release 2026-10-02 20:28:27 +02:00
Ole André Vadla Ravnås 48631baafa subprojects: Bump outdated 2026-10-02 20:27:05 +02:00
Ole André Vadla Ravnås c711f8f040 subprojects: Prepare for release 2026-10-02 01:36:43 +02:00
Ole André Vadla Ravnås 049674da0a subprojects: Bump outdated 2026-10-02 01:32:18 +02:00
Ole André Vadla Ravnås e1c24e8187 bindgen: Marshal null variants as None 2026-10-01 18:24:45 +02:00
Ole André Vadla Ravnås 9947655e6a subprojects: Prepare for release 2026-09-25 13:15:47 +02:00
Ole André Vadla Ravnås e5b15dce63 subprojects: Bump outdated 2026-09-25 13:14:11 +02:00
Ole André Vadla Ravnås e846eb2815 subprojects: Bump outdated 2026-09-25 12:18:59 +02:00
Ole André Vadla Ravnås bc685fd8c1 subprojects: Bump outdated 2026-09-24 21:35:04 +02:00
Ole André Vadla Ravnås bcaa1a099e subprojects: Bump outdated 2026-09-23 00:02:59 +02:00
Ole André Vadla Ravnås 4e782ccbdf submodules: Bump releng 2026-09-23 00:02:58 +02:00
Ole André Vadla Ravnås 9823368745 subprojects: Bump outdated 2026-09-22 23:47:25 +02:00
Ole André Vadla Ravnås c6e5a8d4d9 submodules: Bump releng 2026-09-22 23:47:25 +02:00
Ole André Vadla Ravnås eb15035950 subprojects: Bump outdated 2026-09-22 21:04:23 +02:00
Ole André Vadla Ravnås ec509287e1 subprojects: Bump outdated 2026-09-22 15:57:26 +02:00
Ole André Vadla Ravnås 0c52c00bad submodules: Bump releng 2026-09-22 15:57:26 +02:00
Ole André Vadla Ravnås 8f31efacf2 Format with the current Black
Black has changed how it lays out a call whose argument is a
multiline string, and a `with` statement holding several contexts.
2026-09-17 19:01:25 +02:00
Ole André Vadla Ravnås 01fd680353 bindgen: Fix dropped constructors and out params
A static function that makes the class it sits on was not read at all,
so every named constructor in the API was missing. One that throws was
then missing twice over: skipped for __init__ because it throws, and
skipped as a factory for being the primary, leaving nothing to make
the class with.

An out parameter was dropped along with the value it carried, so a
`gboolean` method that answers through one now binds as Optional, and
any other out parameter is refused rather than bound as a result the
caller cannot read.
2026-09-17 18:54:58 +02:00
Ole André Vadla Ravnås 00e6231b89 subprojects: Bump outdated 2026-09-16 19:28:53 +02:00
10 changed files with 100 additions and 27 deletions

No files matched your search

+4 -2
View File
@@ -42,7 +42,8 @@ class Application:
print("✔ enable_child_gating()")
session.enable_child_gating()
print("✔ create_script()")
script = session.create_script("""\
script = session.create_script(
"""\
Interceptor.attach(Module.getGlobalExportByName('open'), {
onEnter(args) {
send({
@@ -51,7 +52,8 @@ Interceptor.attach(Module.getGlobalExportByName('open'), {
});
}
});
""")
"""
)
script.on("message", lambda message, data: self._reactor.schedule(lambda: self._on_message(pid, message)))
print("✔ load()")
script.load()
+4 -2
View File
@@ -1,7 +1,8 @@
import frida
session = frida.attach("Twitter")
script = session.create_script("""\
script = session.create_script(
"""\
rpc.exports = {
hello: function () {
return 'Hello';
@@ -10,7 +11,8 @@ rpc.exports = {
oops;
}
};
""")
"""
)
script.load()
api = script.exports_sync
print("api.hello() =>", api.hello())
+4 -2
View File
@@ -22,7 +22,8 @@ class Application:
self._session = session
session.on("detached", lambda *args: self._reactor.schedule(lambda: self._on_detached(*args)))
script = session.create_script("""
script = session.create_script(
"""
let _puts = null;
Interceptor.attach(DebugSymbol.getFunctionByName('f'), {
@@ -47,7 +48,8 @@ function puts(s) {
}
_puts(Memory.allocUtf8String(s));
}
""")
"""
)
self._script = script
script.on("message", lambda *args: self._reactor.schedule(lambda: self._on_message(*args)))
script.load()
+4 -2
View File
@@ -29,7 +29,8 @@ class Application:
session = self._device.attach(pid)
session.on("detached", lambda reason: self._reactor.schedule(lambda: self._on_detached(pid, session, reason)))
print("✔ create_script()")
script = session.create_script("""\
script = session.create_script(
"""\
const puts = new NativeFunction(Module.getGlobalExportByName('puts'), 'int', ['pointer']);
puts(Memory.allocUtf8String('Hello from Frida agent'));
Interceptor.attach(Module.getGlobalExportByName('open'), {
@@ -40,7 +41,8 @@ Interceptor.attach(Module.getGlobalExportByName('open'), {
});
}
});
""")
"""
)
script.on("message", lambda message, data: self._reactor.schedule(lambda: self._on_message(pid, message)))
print("✔ load()")
script.load()
@@ -910,6 +910,9 @@ propagate_error:
static PyObject *
PyGObject_marshal_variant (GVariant * variant)
{
if (variant == NULL)
PyFrida_RETURN_NONE;
switch (g_variant_classify (variant))
{
case G_VARIANT_CLASS_STRING:
+70 -16
View File
@@ -436,7 +436,7 @@ def generate_aio_async_method(method: Method, model: Model) -> Optional[str]:
if method.return_value is not None:
call = wrap_result(call, method.return_value.type, model)
ret = "None" if method.return_value is None else pyi_type(method.return_value.type, model)
ret = facade_return_type(method, model)
return f""" async def {method.name}({signature}) -> {ret}:
return {call}"""
@@ -460,7 +460,7 @@ def generate_custom_facade_method(
body = textwrap.indent(logic.strip(), " " * 8)
keyword = "async def" if awaitable else "def"
ret = "None" if method.return_value is None else pyi_type(method.return_value.type, model)
ret = facade_return_type(method, model)
return f""" {keyword} {method.name}({signature}) -> {ret}:
{body}
@@ -667,7 +667,7 @@ def generate_py_sync_method(method: Method, model: Model) -> Optional[str]:
if method.return_value is not None:
call = wrap_result(call, method.return_value.type, model)
ret = "None" if method.return_value is None else pyi_type(method.return_value.type, model)
ret = facade_return_type(method, model)
return f""" def {method.name}({facade_signature(method, params)}) -> {ret}:
return {call}"""
@@ -703,7 +703,7 @@ def generate_py_async_method(method: Method, model: Model) -> Optional[str]:
if method.return_value is not None:
call = wrap_result(call, method.return_value.type, model)
ret = "None" if method.return_value is None else pyi_type(method.return_value.type, model)
ret = facade_return_type(method, model)
return f""" def {method.name}({signature}) -> {ret}:
return {call}"""
@@ -793,8 +793,8 @@ def generate_pyi_class(otype: ObjectType, model: Model) -> List[str]:
body = []
primary = primary_constructor(otype)
if primary is not None and not primary.throws:
primary = inline_constructor(otype)
if primary is not None:
params = pyi_parameters(primary.input_parameters, model)
if params is not None:
signature = ", ".join(["self"] + params)
@@ -869,7 +869,13 @@ def pyi_method(method: Method, model: Model) -> Optional[str]:
if params is None:
return None
signature = ", ".join(["self"] + params)
ret = "None" if method.return_value is None else pyi_type(method.return_value.type, model)
out = method.optional_out_parameter
if out is not None:
ret = f"Optional[{pyi_type(out.type, model)}]"
elif method.return_value is None:
ret = "None"
else:
ret = pyi_type(method.return_value.type, model)
return f" def {method.name}({signature}) -> {ret}: ..."
@@ -1297,13 +1303,15 @@ def generate_object_type_toplevel_definitions(model: Model) -> str:
cprefix = otype.c_symbol_prefix
if otype.name == "Object":
defs.append(f"""PYFRIDA_DEFINE_BASETYPE ("_frida.{otype.py_name}", {otype.py_name}, g_object_unref,
defs.append(
f"""PYFRIDA_DEFINE_BASETYPE ("_frida.{otype.py_name}", {otype.py_name}, g_object_unref,
{{ Py_tp_doc, "{otype.name}" }},
{{ Py_tp_init, {cprefix}_init }},
{{ Py_tp_dealloc, {cprefix}_dealloc }},
{{ Py_tp_methods, {cprefix}_methods }},
{{ Py_tp_getset, {cprefix}_getsets }},
);""")
);"""
)
continue
parent = otype.parent
@@ -1323,12 +1331,14 @@ def generate_object_type_toplevel_definitions(model: Model) -> str:
)
continue
defs.append(f"""PYFRIDA_DEFINE_TYPE ("_frida.{otype.py_name}", {otype.py_name}, {parent_name}, g_object_unref,
defs.append(
f"""PYFRIDA_DEFINE_TYPE ("_frida.{otype.py_name}", {otype.py_name}, {parent_name}, g_object_unref,
{{ Py_tp_doc, "{otype.name}" }},
{{ Py_tp_init, {cprefix}_init }},
{{ Py_tp_methods, {cprefix}_methods }},
{{ Py_tp_getset, {cprefix}_getsets }},
);""")
);"""
)
return "\n\n".join(defs)
@@ -1371,6 +1381,11 @@ def generate_method(otype: ObjectType, method: Method) -> Optional[Tuple[str, st
marshal = synchronous_method_return_marshal(method)
if marshal is None:
return None
out = method.optional_out_parameter
if out is not None:
marshal = build_return_marshal(out.type, method.object_type.model)
if marshal is None:
return None
params = []
for param in method.input_parameters:
sync_param = build_sync_param(param)
@@ -1714,14 +1729,17 @@ def generate_synchronous_method(otype: ObjectType, method: Method, marshal: str,
indent = " " * (len(otype.c_symbol_prefix) + len(method.name) + 3)
handle = f"({otype.c_type} *) PY_GOBJECT_HANDLE (self)"
returns_strv = method.return_value is not None and method.return_value.type.name == "utf8[]"
out = method.optional_out_parameter
call_arg_list = [handle] + [p.call_arg for p in params]
if returns_strv:
call_arg_list.append("&retval_length")
if out is not None:
call_arg_list.append(f"&{out.name}")
if method.throws:
call_arg_list.append("&error")
call = f"{method.c_identifier} ({', '.join(call_arg_list)})"
if not params and not method.throws and not returns_strv:
if not params and not method.throws and not returns_strv and out is None:
if method.return_value is None:
body = f" {call};\n\n PyFrida_RETURN_NONE;"
else:
@@ -1740,6 +1758,8 @@ static PyObject *
decls.append(" GError * error = NULL;")
if returns_strv:
decls.append(" gint retval_length;")
if out is not None:
decls.append(f" {out_parameter_storage_type(out)} {out.name};")
for p in params:
decls += [f" {line}" for line in p.decl.splitlines()]
@@ -1754,7 +1774,15 @@ static PyObject *
pre = "".join(f"\n {p.pre}\n" for p in params if p.pre)
if method.return_value is None:
if out is not None:
invocation = f" gboolean found = {call};"
success = (
" if (found)\n"
f" result = {marshal.format(value=out.name)};\n"
" else\n"
" {\n Py_IncRef (Py_None);\n result = Py_None;\n }"
)
elif method.return_value is None:
invocation = f" {call};"
success = " Py_IncRef (Py_None);\n result = Py_None;"
elif returns_strv:
@@ -1799,6 +1827,22 @@ static PyObject *
"""
def facade_return_type(method: Method, model: Model) -> str:
out = method.optional_out_parameter
if out is not None:
return f"Optional[{pyi_type(out.type, model)}]"
if method.return_value is None:
return "None"
return pyi_type(method.return_value.type, model)
def out_parameter_storage_type(param: Parameter) -> str:
"""What the caller declares: the out parameter's own type, less the pointer."""
c = param.type.c
assert c.endswith("*"), c
return c[:-1].strip()
def synchronous_method_return_marshal(method: Method) -> Optional[str]:
if method.is_async or method.is_property_accessor:
return None
@@ -2328,8 +2372,16 @@ def primary_constructor(otype: ObjectType) -> Optional[Procedure]:
return next((c for c in otype.constructors if c.name == "new"), otype.constructors[0])
def inline_constructor(otype: ObjectType) -> Optional[Procedure]:
"""The constructor __init__ takes; one that throws is reached as a factory instead."""
ctor = primary_constructor(otype)
if ctor is None or ctor.throws:
return None
return ctor
def factory_constructors(otype: ObjectType) -> List[Procedure]:
primary = primary_constructor(otype)
primary = inline_constructor(otype)
return [
ctor
for ctor in otype.constructors
@@ -2716,10 +2768,12 @@ def generate_object_type_structs(model: Model) -> str:
for otype in model.regular_object_types:
if otype.name == "Object":
continue
structs.append(f"""struct _{otype.c_symbol_prefix}
structs.append(
f"""struct _{otype.c_symbol_prefix}
{{
{otype.parent_c_symbol_prefix} parent;
}};""")
}};"""
)
return "\n\n".join(structs)
+8
View File
@@ -17,6 +17,10 @@ class Model(core.Model):
class ObjectType(core.ObjectType):
@cached_property
def methods(self) -> List["Method"]:
return [m for m in super().methods if not m.out_parameters or m.optional_out_parameter is not None]
@cached_property
def py_name(self) -> str:
custom = self.customizations
@@ -277,6 +281,7 @@ def _make_class(
type_struct,
parent,
constructors,
functions,
methods,
properties,
signals,
@@ -291,6 +296,7 @@ def _make_class(
type_struct,
parent,
constructors,
functions,
methods,
properties,
signals,
@@ -307,6 +313,7 @@ def _make_interface(
type_struct,
parent,
constructors,
functions,
methods,
properties,
signals,
@@ -320,6 +327,7 @@ def _make_interface(
type_struct,
parent,
constructors,
functions,
methods,
properties,
signals,
+1 -1
Submodule releng updated: 963fe3826f...4e51c61880.
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/frida-core.git
revision = 17.18.0
revision = 17.23.1
depth = 1
[provide]