diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-05-07 08:56:03 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-05-07 08:56:03 -0700 |
commit | 7d9aa1c81c6342417602ff051fe17814e814cfb6 (patch) | |
tree | 5477d51fc092b121669d44638c87b7961ddf5715 | |
parent | 557bc63442fd7e9a6fb0650a7f80c5eb5781e23a (diff) | |
download | txr-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.c | 14 |
1 files changed, 10 insertions, 4 deletions
@@ -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; } |