summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-10 20:34:50 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-10 20:34:50 -0700
commit2a4693cd5200f87f7effda359e40659955c1ab55 (patch)
tree5ff387769715ec21e6dfe31a9714c86c4d51e376 /ffi.c
parente24b6bf661cb815a1ae1ccd20fb705a6231a8584 (diff)
downloadtxr-2a4693cd5200f87f7effda359e40659955c1ab55.tar.gz
txr-2a4693cd5200f87f7effda359e40659955c1ab55.tar.bz2
txr-2a4693cd5200f87f7effda359e40659955c1ab55.zip
ffi: check against types that can't pass by value.
* ffi.c (ffi_make_call_desc): Throw if any argument type is something with zero size. Throw if the return type has zero size and isn't the type void.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/ffi.c b/ffi.c
index cbd0e7d8..c0378039 100644
--- a/ffi.c
+++ b/ffi.c
@@ -1775,8 +1775,21 @@ val ffi_make_call_desc(val ntotal, val nfixed, val rettype, val argtypes)
tfcd->rettype = rettype;
tfcd->args = args;
- for (i = 0; i < nt; i++)
- args[i] = ffi_get_type(pop(&argtypes));
+ for (i = 0; i < nt; i++) {
+ val type = pop(&argtypes);
+ struct txr_ffi_type *tft = ffi_type_struct_checked(type);
+ if (tft->size == 0)
+ uw_throwf(error_s, lit("~a: can't pass type ~s by value"),
+ self, type, nao);
+ args[i] = tft->ft;
+ }
+
+ {
+ struct txr_ffi_type *tft = ffi_type_struct_checked(rettype);
+ if (tft->size == 0 && tft->ft != &ffi_type_void)
+ uw_throwf(error_s, lit("~a: can't return type ~s by value"),
+ self, rettype, nao);
+ }
if (tfcd->variadic)
ffis = ffi_prep_cif_var(&tfcd->cif, FFI_DEFAULT_ABI, nf, nt,