From 6bd40ff3faeac6704191547a3ba5909b4554ab3c Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 4 May 2017 20:51:44 -0700 Subject: ffi: bugfix: zarray put accessing last element. A zarray of length N is requiring the Lisp vector to be of length N. * ffi.c (ffi_array_put): Reorder logic in the loop so that when we are putting out the terminating null element of a zarray, we do not access the corresponding element of the Lisp vector. Thus if the zarray is N elements wide, the Lisp vector need only be at least N-1 elements wide, not N. (ffi_array_in): Copy the null element of a zarray to the vector only if the vector object at least N elements. If the vector is nil so that we have to construct one, construct a vector of N-1 for a zarray. (ffi_array_get): For a zarray, construct a vector of N-1 elements. Do not even fetch the null. --- ffi.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ffi.c b/ffi.c index 8b3f30db..0cccd46e 100644 --- a/ffi.c +++ b/ffi.c @@ -963,11 +963,13 @@ static val ffi_array_in(struct txr_ffi_type *tft, mem_t *src, val vec, ucnum offs = 0; struct txr_ffi_type *etft = ffi_type_struct(eltype); cnum elsize = etft->size, i; + cnum znelem = if3(tft->null_term && nelem > 0 && + vec && length(vec) < num_fast(nelem), nelem - 1, nelem); if (vec == nil) - vec = vector(num_fast(nelem), nil); + vec = vector(num_fast(znelem), nil); - for (i = 0; i < nelem; i++) { + for (i = 0; i < znelem; i++) { if (etft->in != 0) { val elval = ref(vec, num_fast(i)); refset(vec, num_fast(i), etft->in(etft, src + offs, elval, self)); @@ -993,13 +995,14 @@ static void ffi_array_put(struct txr_ffi_type *tft, val vec, mem_t *dst, ucnum offs = 0; for (i = 0; i < nelem; i++) { - val elval = ref(vec, num_fast(i)); if (nt && i == nelem - 1) { memset(dst + offs, 0, elsize); break; + } else { + val elval = ref(vec, num_fast(i)); + etft->put(etft, elval, dst + offs, self); + offs += elsize; } - etft->put(etft, elval, dst + offs, self); - offs += elsize; } } @@ -1058,12 +1061,13 @@ static val ffi_array_get(struct txr_ffi_type *tft, mem_t *src, val self) } } } else { - val vec = vector(num_fast(nelem), nil); + cnum znelem = if3(tft->null_term && nelem > 0, nelem - 1, nelem); + val vec = vector(num_fast(znelem), nil); struct txr_ffi_type *etft = ffi_type_struct(eltype); cnum elsize = etft->size; cnum offs, i; - for (i = 0, offs = 0; i < nelem; i++) { + for (i = 0, offs = 0; i < znelem; i++) { val elval = etft->get(etft, src + offs, self); refset(vec, num_fast(i), elval); offs += elsize; -- cgit v1.2.3