Ensure that the closure_map is big enough when deserializing.

Also document more invariants about the closure representation,
and avoid some code duplication.

Fixes #1108 (caught by fuzz testing).
This commit is contained in:
Sam Tobin-Hochstadt 2015-10-28 11:31:32 -04:00
parent 9d909d6834
commit 1d3fe10d3d
3 changed files with 16 additions and 5 deletions

View File

@ -792,7 +792,7 @@ static Scheme_Object *write_compiled_closure(Scheme_Object *obj)
svec_size = data->closure_size;
if (SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_TYPED_ARGS) {
svec_size += ((CLOS_TYPE_BITS_PER_ARG * (data->num_params + data->closure_size)) + BITS_PER_MZSHORT - 1) / BITS_PER_MZSHORT;
svec_size += boxmap_size(data->num_params + data->closure_size);
{
int k, mv;
for (k = data->num_params + data->closure_size; --k; ) {
@ -1014,6 +1014,11 @@ static Scheme_Object *read_compiled_closure(Scheme_Object *obj)
if (!(SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_TYPED_ARGS))
data->closure_size = SCHEME_SVEC_LEN(v);
if ((SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_TYPED_ARGS))
if (data->closure_size + boxmap_size(data->closure_size + data->num_params) != SCHEME_SVEC_LEN(v))
return NULL;
data->closure_map = SCHEME_SVEC_VEC(v);
/* If the closure is empty, create the closure now */

View File

@ -1683,7 +1683,7 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
/* closures */
/*========================================================================*/
XFORM_NONGCING static int boxmap_size(int n)
XFORM_NONGCING int boxmap_size(int n)
{
return ((CLOS_TYPE_BITS_PER_ARG * n) + (BITS_PER_MZSHORT - 1)) / BITS_PER_MZSHORT;
}

View File

@ -2709,9 +2709,14 @@ typedef struct Scheme_Closure_Data
Scheme_Inclhash_Object iso; /* keyex used for flags */
mzshort num_params; /* includes collecting arg if has_rest */
mzshort max_let_depth;
mzshort closure_size;
mzshort *closure_map; /* actually a Closure_Info* until resolved; if CLOS_HAS_TYPED_ARGS,
followed by bit array with CLOS_TYPE_BITS_PER_ARG bits per args then per closed-over */
mzshort closure_size; /* the number of closed-over variables */
mzshort *closure_map; /* actually a Closure_Info* until resolved;
contains closure_size elements mapping closed-over var to stack positions.
If CLOS_HAS_TYPED_ARGS, that array is followed by bit array with
CLOS_TYPE_BITS_PER_ARG bits per args then per closed-over
total size = closure_size + (closure_size + num_params) * CLOS_TYPE_BITS_PER_ARG */
Scheme_Object *code;
Scheme_Object *name; /* name or (vector name src line col pos span generated?) */
void *tl_map; /* fixnum or bit array (as array of `int's) indicating which globals+lifts in prefix are used */
@ -2732,6 +2737,7 @@ typedef struct Scheme_Closure_Data
XFORM_NONGCING void scheme_boxmap_set(mzshort *boxmap, int j, int bit, int delta);
XFORM_NONGCING int scheme_boxmap_get(mzshort *boxmap, int j, int delta);
XFORM_NONGCING int boxmap_size(int n);
int scheme_has_method_property(Scheme_Object *code);