summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-24 07:21:30 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-24 07:21:30 -0700
commitc75baad41d9e6cbe11d83e208ccfe35c18a6b19d (patch)
treeefcb1e548443be3fce46102b5bf029ca37d87dd9
parent7c6f1e1ecbd635eb328f6b3e1ebd0b22f9d71594 (diff)
downloadtxr-c75baad41d9e6cbe11d83e208ccfe35c18a6b19d.tar.gz
txr-c75baad41d9e6cbe11d83e208ccfe35c18a6b19d.tar.bz2
txr-c75baad41d9e6cbe11d83e208ccfe35c18a6b19d.zip
ffi: sanity check on object in ffi_val_get.
* ffi.c (ffi_val_get): Throw an exception if the object doesn't appear valid. * gc.c (valid_object_p): New function. Invalid objects are those that are pointers, but either not into a heap, or else to a freed object or to an object that is marked by the garbage collector (should only be seen while GC is running). All others are valid. There can be false positives here: a value with the LIT tag is in fact a pointer, but we don't check whether that is valid. * gc.c (valid_object_p): Declared. * txr.1: Remarks added to documentation of FFI val type.
-rw-r--r--ffi.c6
-rw-r--r--gc.c14
-rw-r--r--gc.h2
-rw-r--r--txr.16
4 files changed, 27 insertions, 1 deletions
diff --git a/ffi.c b/ffi.c
index 84e891e5..d6326d4f 100644
--- a/ffi.c
+++ b/ffi.c
@@ -565,7 +565,11 @@ static void ffi_val_put(struct txr_ffi_type *tft, val v, mem_t *dst, val self)
static val ffi_val_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- return *coerce(val *, src);
+ val v = *coerce(val *, src);
+ if (!valid_object_p(v))
+ uw_throwf(error_s, lit("~a: bit pattern ~0,0*x isn't a valid Lisp object"),
+ self, num_fast(sizeof (v) * 2), bits(v), nao);
+ return v;
}
#if SIZEOF_WCHAR_T == SIZEOF_SHORT
diff --git a/gc.c b/gc.c
index cb67d156..ad3e25bc 100644
--- a/gc.c
+++ b/gc.c
@@ -911,6 +911,20 @@ val gc_call_finalizers(val obj)
return call_finalizers_impl(obj, is_matching_final);
}
+val valid_object_p(val obj)
+{
+ if (!is_ptr(obj))
+ return t;
+
+ if (!in_heap(obj))
+ return nil;
+
+ if (obj->t.type & (REACHABLE | FREE))
+ return nil;
+
+ return t;
+}
+
void gc_late_init(void)
{
reg_fun(intern(lit("gc"), system_package), func_n0(gc_wrap));
diff --git a/gc.h b/gc.h
index 1e67e723..326c5f87 100644
--- a/gc.h
+++ b/gc.h
@@ -47,6 +47,8 @@ val gc_mutated(val);
extern int full_gc;
#endif
+val valid_object_p(val obj);
+
void unmark(void);
void gc_cancel(void);
void gc_hint_func(val *);
diff --git a/txr.1 b/txr.1
index ef497f22..a3277998 100644
--- a/txr.1
+++ b/txr.1
@@ -53414,6 +53414,12 @@ values that aren't objects which came from a Lisp heap.
Interpreting a Lisp value in foreign code requires a correct decoding of
its type tag, and, if necessary, stripping the tag bits to recover a heap
pointer and interpreting the type code stored in the heap object.
+
+The conversion from foreign bit pattern to Lisp value is subject to a
+validity checks; an exception will be thrown if the bit pattern isn't a valid
+Lisp object. Nevertheless, the checks has cases which report as false
+positives: admit some invalid objects may be admitted into the Lisp realm,
+possibly with catastrophic results.
.ccIP @ cptr
This type corresponds to a C pointer of any type, including a function pointer;
\*(TX doesn't run on any exotic platforms in which there is a representational