diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-05-10 20:34:50 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-05-10 20:34:50 -0700 |
commit | 2a4693cd5200f87f7effda359e40659955c1ab55 (patch) | |
tree | 5ff387769715ec21e6dfe31a9714c86c4d51e376 | |
parent | e24b6bf661cb815a1ae1ccd20fb705a6231a8584 (diff) | |
download | txr-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.
-rw-r--r-- | ffi.c | 17 |
1 files changed, 15 insertions, 2 deletions
@@ -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, |