girffi.c: fix return value for g_callable_info_prepare_closure()
The initial failure was observed on meld
against recently released
libffi-3.4-rc1
. There meld
crashes as:
$ meld
Segmentation fault (core dumped)
$ gdb --args /usr/bin/python3.9 /usr/bin/meld
(gdb) run
...
Thread 1 "python3.9" received signal SIGSEGV, Segmentation fault.
0x00007fffe9ac1ae8 in g_callable_info_free_closure (
callable_info=0x555555d45990, closure=0x7fffe9e70c20)
at ../gobject-introspection-1.68.0/girepository/girffi.c:428
428 g_free (wrapper->ffi_closure.cif->arg_types);
(gdb) bt
callable_info=0x555555d45990, closure=0x7fffe9e70c20)
at ../gobject-introspection-1.68.0/girepository/girffi.c:428
data=0x555555d252d0)
at ../pygobject-3.40.1/gi/pygi-closure.c:635
...
The bug here is in type mismatch between expected return value of
g_callable_info_prepare_closure()
and actual value (executable
code pointer):
ffi_closure * g_callable_info_prepare_closure(...) {
gpointer exec_ptr;
...
status = ffi_prep_closure_loc (&closure->ffi_closure, cif, callback, user_data, exec_ptr);
return exec_ptr;
}
Note: exec_ptr
is a code pointer that could be directly executed by
caller, like ((rt (*)(a1,a2))exec_ptr)(1,2);
It should never be wrapped
into an ffi_closure*
, which is normally called via ffi_call(closure, ...)
.
We see the problem when we try to free direct code pointer instead of
ffi_closure()
as starting from libffi-3.4 executable trampoline and
ffi_closure()
don't necessarily live in the same block:
https://github.com/libffi/libffi/commit/9ba559217bea0803263a9a9a0bafcf9203606f5b
Signed-off-by: Sergei Trofimovich slyfox@gentoo.org