summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-04 20:51:44 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-04 20:51:44 -0700
commit33c229bbbbf75ab8b3f048579eb2b7a63acaae7d (patch)
tree18aee90ef9ac3054fdcbf6285711532ea4862ad2 /ffi.c
parente5186dace2ce5c13c2a178b67507a3f917f4ed25 (diff)
downloadtxr-33c229bbbbf75ab8b3f048579eb2b7a63acaae7d.tar.gz
txr-33c229bbbbf75ab8b3f048579eb2b7a63acaae7d.tar.bz2
txr-33c229bbbbf75ab8b3f048579eb2b7a63acaae7d.zip
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.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c18
1 files 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;