From 20f31fb74289a8bf38bf22fe8f47ed6ff0a22c0e Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 12 Oct 2015 19:25:27 -0600 Subject: [PATCH] set a bit to prevent corruption of flags via hashing Certain datatypes in the runtime system are not supposed to be hashed, where bits normally reserved for hash codes are used for other purposes. A bad bytecode file can cause some of those to be hashed, anyway. Normally, the damage is isolated to that content of the damaged bytecode, but certain variable-reference bytecode forms are both shared and non-hashable. Set a bit that ensures hashing will not change flags in the shared object. This problem was exposed by fuzz testing. --- racket/src/racket/src/compenv.c | 8 ++++---- racket/src/racket/src/schpriv.h | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/racket/src/racket/src/compenv.c b/racket/src/racket/src/compenv.c index f2676bd996..4dc3a8f05a 100644 --- a/racket/src/racket/src/compenv.c +++ b/racket/src/racket/src/compenv.c @@ -630,7 +630,7 @@ Scheme_Object *scheme_make_toplevel(mzshort depth, int position, int resolved, i tl->iso.so.type = (resolved ? scheme_toplevel_type : scheme_compiled_toplevel_type); tl->depth = depth; tl->position = position; - SCHEME_TOPLEVEL_FLAGS(tl) = flags; + SCHEME_TOPLEVEL_FLAGS(tl) = flags | HIGH_BIT_TO_DISABLE_HASHING; if (resolved) { if (toplevels_ht->count > TABLE_CACHE_MAX_SIZE) { @@ -801,7 +801,7 @@ static void init_scheme_local() #endif v->type = k + scheme_local_type; SCHEME_LOCAL_POS(v) = i; - SCHEME_LOCAL_FLAGS(v) = cor; + SCHEME_LOCAL_FLAGS(v) = cor | HIGH_BIT_TO_DISABLE_HASHING; scheme_local[i][k][cor] = v; } @@ -841,7 +841,7 @@ static void init_toplevels() v->iso.so.type = scheme_toplevel_type; v->depth = i; v->position = k; - SCHEME_TOPLEVEL_FLAGS(v) = cnst; + SCHEME_TOPLEVEL_FLAGS(v) = cnst | HIGH_BIT_TO_DISABLE_HASHING; toplevels[i][k][cnst] = (Scheme_Object *)v; } @@ -888,7 +888,7 @@ Scheme_Object *scheme_make_local(Scheme_Type type, int pos, int flags) return v; v = alloc_local(type, pos); - SCHEME_LOCAL_FLAGS(v) = flags; + SCHEME_LOCAL_FLAGS(v) = flags | HIGH_BIT_TO_DISABLE_HASHING; if (locals_ht[k]->count > TABLE_CACHE_MAX_SIZE) { Scheme_Hash_Table *ht; diff --git a/racket/src/racket/src/schpriv.h b/racket/src/racket/src/schpriv.h index 0a25dc45b4..b575ee1979 100644 --- a/racket/src/racket/src/schpriv.h +++ b/racket/src/racket/src/schpriv.h @@ -1495,6 +1495,8 @@ typedef struct { Scheme_Object *body; } Scheme_With_Continuation_Mark; +#define HIGH_BIT_TO_DISABLE_HASHING 0x2000 + typedef struct Scheme_Local { Scheme_Inclhash_Object iso; /* keyex used for flags and type info (and can't be hashed) */ mzshort position; @@ -1513,8 +1515,8 @@ typedef struct Scheme_Local { #define SCHEME_LOCAL_OTHER_CLEARS 2 #define SCHEME_LOCAL_TYPE_OFFSET 2 -#define SCHEME_GET_LOCAL_FLAGS(obj) SCHEME_LOCAL_FLAGS(obj) -#define SCHEME_GET_LOCAL_TYPE(obj) ((SCHEME_LOCAL_FLAGS(obj) > 2) ? (SCHEME_LOCAL_FLAGS(obj) - 2) : 0) +#define SCHEME_GET_LOCAL_FLAGS(obj) (SCHEME_LOCAL_FLAGS(obj) & ~HIGH_BIT_TO_DISABLE_HASHING) +#define SCHEME_GET_LOCAL_TYPE(obj) ((SCHEME_GET_LOCAL_FLAGS(obj) > 2) ? (SCHEME_GET_LOCAL_FLAGS(obj) - 2) : 0) typedef struct Scheme_Toplevel { Scheme_Inclhash_Object iso; /* keyex used for flags (and can't be hashed) */