summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-09-30 06:59:05 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-09-30 06:59:05 -0700
commit7098518a9bc43378afb5cbf599a074775c1d1d55 (patch)
tree4aef76fd2598ccdc4d5f1fb13fd056de8e19bb59
parent48ef128584e4b15c8b83de0f10f6d077031fa0ee (diff)
downloadtxr-7098518a9bc43378afb5cbf599a074775c1d1d55.tar.gz
txr-7098518a9bc43378afb5cbf599a074775c1d1d55.tar.bz2
txr-7098518a9bc43378afb5cbf599a074775c1d1d55.zip
safety: fix type tests that code can subvert.
This patch fixes numerous instances of a safety hole which involves the type of a COBJ object being tested to be of a given class using logic that can be subverted by the definition of a like-named struct. Specifically logic like (typeof(obj) == hash_s) is broken, because if a struct type called hash is defined, then the test will yield true for instances of that struct type. Those instances can then be passed into code that only works on COBJ hashes, and relies on this test to reject invalid objects. * ffi.c (make_carray): Replace fragile test with strong one, using new cobjclassp function. * hash.c (hashp): Likewise. * lib.c (class_check): The expression used here for the type test moves into the new function cobjclassp and so is replaced by a call to that function. (cobjclassp): New function. * lib.h (cobjclassp): Declared. * rand.c (random_state_p): Replace fragile test using cobjclassp. * regex.c (char_set_compile): Replace fragile typeof tests for character type with is_chr. (reg_derivative, regexp): Replace fragile test with cobjclassp. * struct.c (struct_type_p): Replace fragile test with cobjclassp.
-rw-r--r--ffi.c2
-rw-r--r--hash.c2
-rw-r--r--lib.c10
-rw-r--r--lib.h1
-rw-r--r--rand.c2
-rw-r--r--regex.c12
-rw-r--r--struct.c2
7 files changed, 19 insertions, 12 deletions
diff --git a/ffi.c b/ffi.c
index 4f79dcc1..816afc41 100644
--- a/ffi.c
+++ b/ffi.c
@@ -4806,7 +4806,7 @@ val make_carray(val type, mem_t *data, cnum nelem, val ref, cnum offs)
val carrayp(val obj)
{
- return tnil(typeof(obj) == carray_s);
+ return cobjclassp(obj, carray_s);
}
val carray_set_length(val carray, val nelem)
diff --git a/hash.c b/hash.c
index 35e22de2..f37d5825 100644
--- a/hash.c
+++ b/hash.c
@@ -919,7 +919,7 @@ val set_hash_userdata(val hash, val data)
val hashp(val obj)
{
- return typeof(obj) == hash_s ? t : nil;
+ return cobjclassp(obj, hash_s);
}
static void hash_iter_mark(val hash_iter)
diff --git a/lib.c b/lib.c
index 3e439437..ef781a89 100644
--- a/lib.c
+++ b/lib.c
@@ -499,8 +499,7 @@ val throw_mismatch(val self, val obj, type_t t)
val class_check(val self, val cobj, val class_sym)
{
- type_assert (is_ptr(cobj) && cobj->t.type == COBJ &&
- (cobj->co.cls == class_sym || subtypep(cobj->co.cls, class_sym)),
+ type_assert (cobjclassp(cobj, class_sym),
(lit("~a: ~s is not of type ~s"), self, cobj, class_sym, nao));
return t;
}
@@ -7828,6 +7827,13 @@ val cobjp(val obj)
return type(obj) == COBJ ? t : nil;
}
+val cobjclassp(val obj, val cls_sym)
+{
+ return if2(is_ptr(obj) && obj->t.type == COBJ &&
+ (obj->co.cls == cls_sym || subtypep(obj->co.cls, cls_sym)),
+ one);
+}
+
mem_t *cobj_handle(val self, val cobj, val cls_sym)
{
class_check(self, cobj, cls_sym);
diff --git a/lib.h b/lib.h
index e47b84c6..7c8a582b 100644
--- a/lib.h
+++ b/lib.h
@@ -1027,6 +1027,7 @@ val length_str_lt(val str, val len);
val length_str_le(val str, val len);
val cobj(mem_t *handle, val cls_sym, struct cobj_ops *ops);
val cobjp(val obj);
+val cobjclassp(val obj, val cls_sym);
mem_t *cobj_handle(val self, val cobj, val cls_sym);
struct cobj_ops *cobj_ops(val self, val cobj, val cls_sym);
val cptr(mem_t *ptr);
diff --git a/rand.c b/rand.c
index 91d122ec..ce3a69a7 100644
--- a/rand.c
+++ b/rand.c
@@ -83,7 +83,7 @@ static val make_state(void)
val random_state_p(val obj)
{
- return typeof(obj) == random_state_s ? t : nil;
+ return cobjclassp(obj, random_state_s);
}
INLINE rand32_t *rstate(struct rand_state *r, int offs)
diff --git a/regex.c b/regex.c
index 50a246c7..d4008b38 100644
--- a/regex.c
+++ b/regex.c
@@ -682,7 +682,7 @@ static char_set_t *char_set_compile(val args, val comp)
val from = car(item);
val to = cdr(item);
- assert (typeof(from) == chr_s && typeof(to) == chr_s);
+ assert (is_chr(from) && is_chr(to));
if (c_chr(from) < min)
min = c_chr(from);
@@ -693,7 +693,7 @@ static char_set_t *char_set_compile(val args, val comp)
min = c_chr(to);
if (c_chr(to) > max)
max = c_chr(to);
- } else if (typeof(item) == chr_s) {
+ } else if (is_chr(item)) {
if (c_chr(item) < min)
min = c_chr(item);
if (c_chr(item) > max)
@@ -745,9 +745,9 @@ static char_set_t *char_set_compile(val args, val comp)
val from = car(item);
val to = cdr(item);
- assert (typeof(from) == chr_s && typeof(to) == chr_s);
+ assert (is_chr(from) && is_chr(to));
char_set_add_range(set, c_chr(from), c_chr(to));
- } else if (typeof(item) == chr_s) {
+ } else if (is_chr(item)) {
char_set_add(set, c_chr(item));
} else if (item == space_k) {
char_set_add_str(set, spaces);
@@ -1835,7 +1835,7 @@ static val reg_derivative(val exp, val ch)
return t;
} else if (chrp(exp)) {
return null(eq(exp, ch));
- } else if (typeof(exp) == chset_s) {
+ } else if (cobjclassp(exp, chset_s)) {
char_set_t *set = coerce(char_set_t *, exp->co.handle);
return if3(char_set_contains(set, c_chr(ch)), nil, t);
} else if (exp == wild_s) {
@@ -2240,7 +2240,7 @@ val regex_compile(val regex_sexp, val error_stream)
val regexp(val obj)
{
- return typeof(obj) == regex_s ? t : nil;
+ return cobjclassp(obj, regex_s);
}
val regex_source(val compiled_regex)
diff --git a/struct.c b/struct.c
index 82ea5ef4..956506d2 100644
--- a/struct.c
+++ b/struct.c
@@ -433,7 +433,7 @@ val find_struct_type(val sym)
val struct_type_p(val obj)
{
- return tnil(typeof(obj) == struct_type_s);
+ return cobjclassp(obj, struct_type_s);
}
val struct_get_initfun(val type)