summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-10-17 07:54:24 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-10-17 07:54:24 -0700
commite61bfc41ed9d522b8f679e758fe79f20b326b76b (patch)
tree187f81f89351609fb940056b858d8424c0e35ad9
parent24f59dc6fd38aeba9a10099c8b7a1243b18392a3 (diff)
downloadtxr-e61bfc41ed9d522b8f679e758fe79f20b326b76b.tar.gz
txr-e61bfc41ed9d522b8f679e758fe79f20b326b76b.tar.bz2
txr-e61bfc41ed9d522b8f679e758fe79f20b326b76b.zip
vm: prevent overflow of fixparam field in function.
Functions can only have 127 fixed parameters; some code ignores this when assigning to the bitfield. * lib.h (FIXPARAM_BITS, FIXPARAM_MAX): New preprocessor symbols. (struct func): Use FIXPARAM_BITS for defining fixparam and optargs bitfields instead of hard-coded 7. * lib.c (func_vm): Sanity check the fixparam and reqags parameters: 0 <= reqargs <= fixparam <= FIXPARAM_MAX.
-rw-r--r--lib.c26
-rw-r--r--lib.h7
2 files changed, 22 insertions, 11 deletions
diff --git a/lib.c b/lib.c
index ba129115..411bfd4a 100644
--- a/lib.c
+++ b/lib.c
@@ -6128,15 +6128,23 @@ val func_interp(val env, val form)
val func_vm(val closure, val desc, int fixparam, int reqargs, int variadic)
{
- val obj = make_obj();
- obj->f.type = FUN;
- obj->f.functype = FVM;
- obj->f.env = closure;
- obj->f.f.vm_desc = desc;
- obj->f.fixparam = fixparam;
- obj->f.optargs = fixparam - reqargs;
- obj->f.variadic = (variadic != 0);
- return obj;
+ if (fixparam > FIXPARAM_MAX) {
+ uw_throwf(error_s, lit("closure in ~s with more than ~s fixed parameters"),
+ desc, unum(FIXPARAM_MAX), nao);
+ } else if (fixparam < 0 || reqargs < 0 || reqargs > fixparam) {
+ uw_throwf(error_s, lit("closure in ~s with bogus parameters"),
+ desc, nao);
+ } else {
+ val obj = make_obj();
+ obj->f.type = FUN;
+ obj->f.functype = FVM;
+ obj->f.env = closure;
+ obj->f.f.vm_desc = desc;
+ obj->f.fixparam = fixparam;
+ obj->f.optargs = fixparam - reqargs;
+ obj->f.variadic = (variadic != 0);
+ return obj;
+ }
}
val copy_fun(val ofun)
diff --git a/lib.h b/lib.h
index bd5fbfc3..35da0a43 100644
--- a/lib.h
+++ b/lib.h
@@ -147,10 +147,13 @@ struct package {
typedef struct args *varg;
+#define FIXPARAM_BITS 7
+#define FIXPARAM_MAX ((1U << FIXPARAM_BITS) - 1)
+
struct func {
obj_common;
- unsigned fixparam : 7; /* total non-variadic parameters */
- unsigned optargs : 7; /* fixparam - optargs = required args */
+ unsigned fixparam : FIXPARAM_BITS; /* total non-variadic parameters */
+ unsigned optargs : FIXPARAM_BITS; /* fixparam - optargs = required args */
unsigned variadic : 1;
unsigned : 1;
unsigned functype : 16;