summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-05-17 20:52:44 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-05-17 20:52:44 -0700
commitdd9ab5fc0b6c0b706288f8f5e20989b6e24921e9 (patch)
treec58d46d42e22737ae2a7d97df3c16802b3217925 /ffi.c
parent84f3ab45a75a881cf7959edd381bbcd0ee828ed5 (diff)
downloadtxr-dd9ab5fc0b6c0b706288f8f5e20989b6e24921e9.tar.gz
txr-dd9ab5fc0b6c0b706288f8f5e20989b6e24921e9.tar.bz2
txr-dd9ab5fc0b6c0b706288f8f5e20989b6e24921e9.zip
ffi: bugfix: null terminated string as flexible member.
* ffi.c (ffi_char_array_get, ffi_zchar_array_get, ffi_wchar_array_get, ffi_bchar_array_get): Rearrange so that we test for tft->null_term first, and not nelem == 0. If nelem happens to be zero, but we are supposed to decode a null-terminated string, we will do the wrong thing and return the null string. (ffi_varray_in): The body can't be conditional on vec being non-nil, because then we do nothing if we don't have a Lisp object, which means we skip the cases when we should decode a null-terminated array. Now if vec is nil, we must guard against calling ffi_varray_dynsize.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c66
1 files changed, 28 insertions, 38 deletions
diff --git a/ffi.c b/ffi.c
index a12ef4a3..c8c8ca82 100644
--- a/ffi.c
+++ b/ffi.c
@@ -2460,16 +2460,14 @@ static void ffi_struct_release(struct txr_ffi_type *tft, val strct,
static val ffi_char_array_get(struct txr_ffi_type *tft, mem_t *src,
cnum nelem)
{
- if (nelem == 0) {
+ const char *chptr = coerce(const char *, src);
+ if (tft->null_term) {
+ return string_utf8(chptr);
+ } else if (nelem == 0) {
return null_string;
} else {
- const char *chptr = coerce(const char *, src);
- if (tft->null_term) {
- return string_utf8(chptr);
- } else {
- wchar_t *wch = utf8_dup_from_buf(chptr, nelem);
- return string_own(wch);
- }
+ wchar_t *wch = utf8_dup_from_buf(chptr, nelem);
+ return string_own(wch);
}
}
@@ -2496,36 +2494,30 @@ static void ffi_char_array_put(struct txr_ffi_type *tft, val str, mem_t *dst,
static val ffi_zchar_array_get(struct txr_ffi_type *tft, mem_t *src,
cnum nelem)
{
- if (nelem == 0) {
+ const char *chptr = coerce(const char *, src);
+ if (tft->null_term) {
+ return string_utf8(chptr);
+ } else if (nelem == 0) {
return null_string;
+ } else if (memchr(chptr, 0, nelem)) {
+ return string_utf8(chptr);
} else {
- const char *chptr = coerce(const char *, src);
- if (tft->null_term) {
- return string_utf8(chptr);
- } else if (memchr(chptr, 0, nelem)) {
- return string_utf8(chptr);
- } else {
- wchar_t *wch = utf8_dup_from_buf(chptr, nelem);
- return string_own(wch);
- }
+ wchar_t *wch = utf8_dup_from_buf(chptr, nelem);
+ return string_own(wch);
}
}
-
static val ffi_wchar_array_get(struct txr_ffi_type *tft, mem_t *src,
cnum nelem, val self)
{
- if (nelem == 0) {
+ const wchar_t *wchptr = coerce(const wchar_t *, src);
+ if (tft->null_term) {
+ return string(wchptr);
+ } else if (nelem == 0) {
return null_string;
} else {
- const wchar_t *wchptr = coerce(const wchar_t *, src);
-
- if (tft->null_term) {
- return string(wchptr);
- } else {
- val ustr = mkustring(num_fast(nelem));
- return init_str(ustr, wchptr, self);
- }
+ val ustr = mkustring(num_fast(nelem));
+ return init_str(ustr, wchptr, self);
}
}
@@ -2541,15 +2533,13 @@ static void ffi_wchar_array_put(struct txr_ffi_type *tft, val str, mem_t *dst,
static val ffi_bchar_array_get(struct txr_ffi_type *tft, mem_t *src,
cnum nelem)
{
- if (nelem == 0) {
+ const unsigned char *chptr = coerce(const unsigned char *, src);
+ if (tft->null_term)
+ return string_8bit(chptr);
+ else if (nelem == 0)
return null_string;
- } else {
- const unsigned char *chptr = coerce(const unsigned char *, src);
- if (tft->null_term)
- return string_8bit(chptr);
- else
- return string_8bit_size(chptr, nelem);
- }
+ else
+ return string_8bit_size(chptr, nelem);
}
static void ffi_bchar_array_put(struct txr_ffi_type *tft, val str, mem_t *dst,
@@ -2858,9 +2848,9 @@ static void ffi_varray_put(struct txr_ffi_type *tft, val vec, mem_t *dst,
static val ffi_varray_in(struct txr_ffi_type *tft, int copy, mem_t *src,
val vec, val self)
{
- if (copy && vec) {
+ if (copy) {
struct txr_ffi_type *etft = ffi_type_struct(tft->eltype);
- cnum nelem = ffi_varray_dynsize(tft, vec, self) / etft->size;
+ cnum nelem = if3(vec, ffi_varray_dynsize(tft, vec, self) / etft->size, 0);
switch (tft->ch_conv) {
case conv_char: