summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-07 08:56:03 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-07 08:56:03 -0700
commit7d9aa1c81c6342417602ff051fe17814e814cfb6 (patch)
tree5477d51fc092b121669d44638c87b7961ddf5715
parent557bc63442fd7e9a6fb0650a7f80c5eb5781e23a (diff)
downloadtxr-7d9aa1c81c6342417602ff051fe17814e814cfb6.tar.gz
txr-7d9aa1c81c6342417602ff051fe17814e814cfb6.tar.bz2
txr-7d9aa1c81c6342417602ff051fe17814e814cfb6.zip
ffi: bugfix: all out calls must fall back on put.
* ffi.c (ffi_struct_out, ffi_array_out): For any element which has no out function, do a put if the copy flag is true. Otherwise callbacks cannot update members in aggregates passed by pointer.
-rw-r--r--ffi.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/ffi.c b/ffi.c
index 6c366738..1a9ebb01 100644
--- a/ffi.c
+++ b/ffi.c
@@ -909,13 +909,16 @@ static void ffi_struct_out(struct txr_ffi_type *tft, int copy, val strct,
struct txr_ffi_type *mtft = ffi_type_struct(type);
ucnum almask = mtft->align - 1;
offs = (offs + almask) & ~almask;
- if (mtft->out != 0) {
- if (slsym) {
+ if (slsym) {
+ if (mtft->out != 0) {
val slval = slot(strct, slsym);
mtft->out(mtft, copy, slval, dst + offs, self);
- } else {
- memset(dst + offs, 0, mtft->size);
+ } else if (copy) {
+ val slval = slot(strct, slsym);
+ mtft->put(mtft, slval, dst + offs, self);
}
+ } else if (copy) {
+ memset(dst + offs, 0, mtft->size);
}
offs += mtft->size;
}
@@ -1061,6 +1064,9 @@ static void ffi_array_out(struct txr_ffi_type *tft, int copy, val vec,
if (etft->out != 0) {
val elval = ref(vec, num_fast(i));
etft->out(etft, copy, elval, dst + offs, self);
+ } else if (copy) {
+ val elval = ref(vec, num_fast(i));
+ etft->put(etft, elval, dst + offs, self);
}
offs += elsize;
}