diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-05-13 08:55:43 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-05-13 08:55:43 -0700 |
commit | 0a2773aa2c585d01037c36b5cc6ccf3be7eac314 (patch) | |
tree | c49a499fc3fa1c4eb92be63b279e2d3cb6a96c90 | |
parent | 396830c9122ea7973cfcf406421671c82604128c (diff) | |
download | txr-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.c | 39 |
1 files changed, 24 insertions, 15 deletions
@@ -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; } |