summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-13 08:55:43 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-13 08:55:43 -0700
commit0a2773aa2c585d01037c36b5cc6ccf3be7eac314 (patch)
treec49a499fc3fa1c4eb92be63b279e2d3cb6a96c90
parent396830c9122ea7973cfcf406421671c82604128c (diff)
downloadtxr-0a2773aa2c585d01037c36b5cc6ccf3be7eac314.tar.gz
txr-0a2773aa2c585d01037c36b5cc6ccf3be7eac314.tar.bz2
txr-0a2773aa2c585d01037c36b5cc6ccf3be7eac314.zip
ffi: null out all freed or borrowed pointers.
When taking ownership of any pointer from FFI space, null it out. This is safer in general and prevents corruption problems in the callback interface when an exception is thrown. For instance (ptr wstr-d) callback argument: callback takes ownership of the pointer in a string object; throws an exception. The FFI call dispatch runs the in semantics to get the string value out; but the old pointer is still there which may not be used. * ffi.c (ffi_str_d_get, ffi_wstr_d_get, ffi_bstr_d_get, ffi_buf_d_in, ffi_buf_d_get, ffi_ptr_d_get): Overwrite the source location of a freed or owned pointer with null.
-rw-r--r--ffi.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/ffi.c b/ffi.c
index 055d88d1..1fef6402 100644
--- a/ffi.c
+++ b/ffi.c
@@ -612,9 +612,10 @@ static val ffi_str_get(struct txr_ffi_type *tft, mem_t *src, val self)
static val ffi_str_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- char *p = *coerce(char **, src);
- val ret = p ? string_utf8(p) : nil;
- free(p);
+ char **loc = coerce(char **, src);
+ val ret = *loc ? string_utf8(*loc) : nil;
+ free(*loc);
+ *loc = 0;
return ret;
}
@@ -648,8 +649,10 @@ static void ffi_wstr_put(struct txr_ffi_type *tft, val s, mem_t *dst,
static val ffi_wstr_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- wchar_t *p = *coerce(wchar_t **, src);
- return p ? string_own(p) : nil;
+ wchar_t **loc = coerce(wchar_t **, src);
+ val ret = *loc ? string_own(*loc) : nil;
+ *loc = 0;
+ return ret;
}
static val ffi_bstr_in(struct txr_ffi_type *tft, int copy,
@@ -683,9 +686,10 @@ static val ffi_bstr_get(struct txr_ffi_type *tft, mem_t *src, val self)
static val ffi_bstr_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- unsigned char *p = *coerce(unsigned char **, src);
- val ret = p ? string_8bit(p) : nil;
- free(p);
+ unsigned char **loc = coerce(unsigned char **, src);
+ val ret = *loc ? string_8bit(*loc) : nil;
+ free(*loc);
+ *loc = 0;
return ret;
}
@@ -725,10 +729,12 @@ static val ffi_buf_d_in(struct txr_ffi_type *tft, int copy, mem_t *src,
mem_t *origptr = buf_get(obj, self);
if (*loc != origptr) {
- if (copy)
+ if (copy) {
obj = make_borrowed_buf(length_buf(obj), *loc);
- else
+ } else {
free(*loc);
+ *loc = 0;
+ }
}
return obj;
@@ -747,8 +753,10 @@ static void ffi_buf_d_put(struct txr_ffi_type *tft, val buf, mem_t *dst,
static val ffi_buf_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- mem_t *p = *coerce(mem_t **, src);
- return p ? make_borrowed_buf(num(tft->nelem), p) : nil;
+ mem_t **loc = coerce(mem_t **, src);
+ val ret = *loc ? make_borrowed_buf(num(tft->nelem), *loc) : nil;
+ *loc = 0;
+ return ret;
}
static void ffi_closure_put(struct txr_ffi_type *tft, val ptr, mem_t *dst,
@@ -857,9 +865,10 @@ static val ffi_ptr_d_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
val tgttype = tft->mtypes;
struct txr_ffi_type *tgtft = ffi_type_struct(tgttype);
- mem_t *ptr = *coerce(mem_t **, src);
- val ret = ptr ? tgtft->get(tgtft, ptr, self) : nil;
- free(ptr);
+ mem_t **loc = coerce(mem_t **, src);
+ val ret = *loc ? tgtft->get(tgtft, *loc, self) : nil;
+ free(*loc);
+ *loc = 0;
return ret;
}