From 5b142b33425b7dbd8e27d840fd2d38ac192d150d Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 17 Oct 2019 07:54:24 -0700 Subject: 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. --- lib.c | 26 +++++++++++++++++--------- lib.h | 7 +++++-- 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; -- cgit v1.2.3