add some missing checks on bytecode parsing
The `tests/racket/stress/fuzz' test fails much less frequently, though problems certainly remain.
This commit is contained in:
parent
657be87c66
commit
4a387c5b6a
|
@ -8,8 +8,15 @@
|
|||
(bytes-set! bs byte (bitwise-xor (expt 2 bit) val)))
|
||||
|
||||
(define (run-file bs)
|
||||
(eval (parameterize ([read-accept-compiled #t])
|
||||
(with-input-from-bytes bs read))))
|
||||
(sync
|
||||
(parameterize ([current-custodian (make-custodian)])
|
||||
(thread
|
||||
(lambda ()
|
||||
(custodian-limit-memory (current-custodian)
|
||||
(* 512 (expt 2 20)))
|
||||
(with-handlers ([void void])
|
||||
(eval (parameterize ([read-accept-compiled #t])
|
||||
(with-input-from-bytes bs read)))))))))
|
||||
|
||||
(define (run fname seed0)
|
||||
(define seed (or seed0 (+ 1 (random (expt 2 30)))))
|
||||
|
@ -21,17 +28,20 @@
|
|||
(for ([i (in-range (quotient len 10000))]) (flip-bit bs (random len)))
|
||||
(with-handlers ([void void]) (run-file bs)))
|
||||
|
||||
(let ([seed #f] [file #f] [dir #f])
|
||||
(let ([seed0 #f] [file #f] [dir #f] [forever? #f])
|
||||
(command-line
|
||||
#:once-each
|
||||
["-s" seed "random seed" (set! seed (string->number seed))]
|
||||
["-s" seed "random seed" (set! seed0 (string->number seed))]
|
||||
["--oo" "forever" (set! forever? #t)]
|
||||
#:once-any
|
||||
["-f" file "filename to run" (set! file file)]
|
||||
["-d" dir* "dir to run" (set! dir dir*)]
|
||||
["-c" "run over all collections" (set! dir (find-collects-dir))]
|
||||
#:args () (void))
|
||||
(cond [file (run file seed)]
|
||||
[dir (for ([p (in-directory dir)]
|
||||
#:when (regexp-match #rx"\\.zo" p))
|
||||
(run p seed))]
|
||||
[else (printf "Nothing to do.\n")]))
|
||||
(let loop ()
|
||||
(cond [file (run file seed0)]
|
||||
[dir (for ([p (in-directory dir)]
|
||||
#:when (regexp-match #rx"\\.zo" p))
|
||||
(run p seed0))]
|
||||
[else (printf "Nothing to do.\n")])
|
||||
(when forever? (loop))))
|
||||
|
|
|
@ -4127,12 +4127,24 @@ Scheme_Object *scheme_make_application(Scheme_Object *v)
|
|||
Scheme_App_Rec *scheme_malloc_application(int n)
|
||||
{
|
||||
Scheme_App_Rec *app;
|
||||
int size;
|
||||
intptr_t size;
|
||||
|
||||
size = (sizeof(Scheme_App_Rec)
|
||||
+ ((n - mzFLEX_DELTA) * sizeof(Scheme_Object *))
|
||||
+ n * sizeof(char));
|
||||
app = (Scheme_App_Rec *)scheme_malloc_tagged(size);
|
||||
if (n < 0) {
|
||||
scheme_signal_error("bad application count");
|
||||
app = NULL;
|
||||
} else if (n > 4096) {
|
||||
size = scheme_check_overflow(n,
|
||||
sizeof(char),
|
||||
(sizeof(Scheme_App_Rec)
|
||||
+ ((n - mzFLEX_DELTA) * sizeof(Scheme_Object *))));
|
||||
app = (Scheme_App_Rec *)scheme_malloc_fail_ok(scheme_malloc_tagged, size);
|
||||
if (!app) scheme_signal_error("out of memory allocating application bytecode");
|
||||
} else {
|
||||
size = (sizeof(Scheme_App_Rec)
|
||||
+ ((n - mzFLEX_DELTA) * sizeof(Scheme_Object *))
|
||||
+ n * sizeof(char));
|
||||
app = (Scheme_App_Rec *)scheme_malloc_tagged(size);
|
||||
}
|
||||
|
||||
app->so.type = scheme_application_type;
|
||||
|
||||
|
|
|
@ -1352,6 +1352,10 @@ Scheme_Object **scheme_make_builtin_references_table(void)
|
|||
scheme_misc_count += sizeof(Scheme_Object *) * (builtin_ref_counter + 1);
|
||||
#endif
|
||||
|
||||
for (j = builtin_ref_counter + 1; j--; ) {
|
||||
t[j] = scheme_false;
|
||||
}
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (!j)
|
||||
kenv = kernel_env;
|
||||
|
|
|
@ -275,7 +275,13 @@ static Scheme_Object *read_letrec(Scheme_Object *obj)
|
|||
lr->body = SCHEME_CAR(obj);
|
||||
obj = SCHEME_CDR(obj);
|
||||
|
||||
sa = MALLOC_N(Scheme_Object*, c);
|
||||
if (c < 0) return NULL;
|
||||
if (c < 4096)
|
||||
sa = MALLOC_N(Scheme_Object*, c);
|
||||
else {
|
||||
sa = scheme_malloc_fail_ok(scheme_malloc, scheme_check_overflow(c, sizeof(Scheme_Object *), 0));
|
||||
if (!sa) scheme_signal_error("out of memory allocating letrec bytecode");
|
||||
}
|
||||
lr->procs = sa;
|
||||
for (i = 0; i < c; i++) {
|
||||
if (!SCHEME_PAIRP(obj)) return NULL;
|
||||
|
@ -312,6 +318,8 @@ static Scheme_Object *read_top(Scheme_Object *obj)
|
|||
if (!SCHEME_PAIRP(obj)) return NULL;
|
||||
top->prefix = (Resolve_Prefix *)SCHEME_CAR(obj);
|
||||
top->code = SCHEME_CDR(obj);
|
||||
if (!SAME_TYPE(SCHEME_TYPE(top->prefix), scheme_resolve_prefix_type))
|
||||
return NULL;
|
||||
|
||||
return (Scheme_Object *)top;
|
||||
}
|
||||
|
@ -585,6 +593,8 @@ static Scheme_Object *read_sequence_save_first(Scheme_Object *obj)
|
|||
static Scheme_Object *read_sequence_splice(Scheme_Object *obj)
|
||||
{
|
||||
obj = scheme_make_sequence_compilation(obj, 1);
|
||||
if (!obj) return NULL;
|
||||
|
||||
if (SAME_TYPE(SCHEME_TYPE(obj), scheme_sequence_type))
|
||||
obj->type = scheme_splice_sequence_type;
|
||||
return obj;
|
||||
|
@ -958,6 +968,9 @@ static Scheme_Object *read_toplevel(Scheme_Object *obj)
|
|||
flags = 0;
|
||||
}
|
||||
|
||||
if (depth < 0) return NULL;
|
||||
if (pos < 0) return NULL;
|
||||
|
||||
return scheme_make_toplevel(depth, pos, 1, flags);
|
||||
}
|
||||
|
||||
|
@ -1029,6 +1042,7 @@ static Scheme_Object *do_read_local(Scheme_Type t, Scheme_Object *obj)
|
|||
flags = 0;
|
||||
|
||||
n = (int)SCHEME_INT_VAL(obj);
|
||||
if (n < 0) return NULL;
|
||||
|
||||
return scheme_make_local(t, n, flags);
|
||||
}
|
||||
|
@ -1086,7 +1100,7 @@ static Scheme_Object *write_resolve_prefix(Scheme_Object *obj)
|
|||
static Scheme_Object *read_resolve_prefix(Scheme_Object *obj)
|
||||
{
|
||||
Resolve_Prefix *rp;
|
||||
Scheme_Object *tv, *sv, **a, *stx;
|
||||
Scheme_Object *tv, *sv, **a, *stx, *tl;
|
||||
intptr_t i;
|
||||
|
||||
if (!SCHEME_PAIRP(obj)) return NULL;
|
||||
|
@ -1119,7 +1133,15 @@ static Scheme_Object *read_resolve_prefix(Scheme_Object *obj)
|
|||
i = rp->num_toplevels;
|
||||
a = MALLOC_N(Scheme_Object *, i);
|
||||
while (i--) {
|
||||
a[i] = SCHEME_VEC_ELS(tv)[i];
|
||||
tl = SCHEME_VEC_ELS(tv)[i];
|
||||
if (!SCHEME_FALSEP(tl)
|
||||
&& !SCHEME_SYMBOLP(tl)
|
||||
&& (!SCHEME_PAIRP(tl)
|
||||
|| !SCHEME_SYMBOLP(SCHEME_CAR(tl)))
|
||||
&& !SAME_TYPE(SCHEME_TYPE(tl), scheme_variable_type)
|
||||
&& !SAME_TYPE(SCHEME_TYPE(tl), scheme_module_variable_type))
|
||||
return NULL;
|
||||
a[i] = tl;
|
||||
}
|
||||
rp->toplevels = a;
|
||||
|
||||
|
|
|
@ -4066,6 +4066,7 @@ typedef struct Scheme_Load_Delay {
|
|||
|
||||
#define ZO_CHECK(x) if (!(x)) scheme_ill_formed_code(port);
|
||||
#define RANGE_CHECK(x, y) ZO_CHECK (x y)
|
||||
#define RANGE_POS_CHECK(x, y) ZO_CHECK ((x > 0) && (x y))
|
||||
#define RANGE_CHECK_GETS(x) RANGE_CHECK(x, <= port->size - port->pos)
|
||||
|
||||
typedef struct CPort {
|
||||
|
@ -4179,13 +4180,22 @@ static Scheme_Object *read_compact_svector(CPort *port, int l)
|
|||
o->type = scheme_svector_type;
|
||||
|
||||
SCHEME_SVEC_LEN(o) = l;
|
||||
if (l > 0)
|
||||
v = MALLOC_N_ATOMIC(mzshort, l);
|
||||
else
|
||||
if (l > 0) {
|
||||
if (l > 4096) {
|
||||
v = (mzshort *)scheme_malloc_fail_ok(scheme_malloc_atomic,
|
||||
scheme_check_overflow(l, sizeof(mzshort), 0));
|
||||
if (!v)
|
||||
scheme_signal_error("out of memory allocating vector");
|
||||
} else {
|
||||
v = MALLOC_N_ATOMIC(mzshort, l);
|
||||
}
|
||||
} else {
|
||||
v = NULL;
|
||||
l = 0; /* in case it was negative */
|
||||
}
|
||||
SCHEME_SVEC_VEC(o) = v;
|
||||
|
||||
while (l--) {
|
||||
while (l-- > 0) {
|
||||
mzshort cn;
|
||||
cn = read_compact_number(port);
|
||||
v[l] = cn;
|
||||
|
@ -4295,7 +4305,7 @@ static Scheme_Object *read_compact(CPort *port, int use_stack)
|
|||
break;
|
||||
case CPT_SYMREF:
|
||||
l = read_compact_number(port);
|
||||
RANGE_CHECK(l, < port->symtab_size);
|
||||
RANGE_POS_CHECK(l, < port->symtab_size);
|
||||
v = port->symtab[l];
|
||||
if (v == SYMTAB_IN_PROGRESS) {
|
||||
/* there is a cycle */
|
||||
|
@ -4351,8 +4361,12 @@ static Scheme_Object *read_compact(CPort *port, int use_stack)
|
|||
l = read_compact_number(port);
|
||||
RANGE_CHECK_GETS(el);
|
||||
s = read_compact_chars(port, buffer, BLK_BUF_SIZE, el);
|
||||
us = (mzchar *)scheme_malloc_atomic((l + 1) * sizeof(mzchar));
|
||||
scheme_utf8_decode_all((const unsigned char *)s, el, us, 0);
|
||||
if (l < 4096)
|
||||
us = (mzchar *)scheme_malloc_atomic((l + 1) * sizeof(mzchar));
|
||||
else
|
||||
us = (mzchar *)scheme_malloc_fail_ok(scheme_malloc_atomic, (l + 1) * sizeof(mzchar));
|
||||
if (scheme_utf8_decode((const unsigned char *)s, 0, el, us, 0, l, NULL, 0, 0) != l)
|
||||
scheme_ill_formed_code(port);
|
||||
us[l] = 0;
|
||||
v = scheme_make_immutable_sized_char_string(us, l, 0);
|
||||
v = scheme_intern_literal_string(v);
|
||||
|
@ -4648,6 +4662,7 @@ static Scheme_Object *read_compact(CPort *port, int use_stack)
|
|||
port->symtab[l] = (Scheme_Object *)cl;
|
||||
v = read_compact(port, 0);
|
||||
if (!SAME_TYPE(SCHEME_TYPE(v), scheme_closure_type)
|
||||
|| !((Scheme_Closure *)v)->code
|
||||
|| ((Scheme_Closure *)v)->code->closure_size) {
|
||||
scheme_ill_formed_code(port);
|
||||
return NULL;
|
||||
|
@ -4659,7 +4674,7 @@ static Scheme_Object *read_compact(CPort *port, int use_stack)
|
|||
case CPT_DELAY_REF:
|
||||
{
|
||||
l = read_compact_number(port);
|
||||
RANGE_CHECK(l, < port->symtab_size);
|
||||
RANGE_POS_CHECK(l, < port->symtab_size);
|
||||
v = port->symtab[l];
|
||||
if (!v) {
|
||||
if (port->delay_info) {
|
||||
|
@ -4675,6 +4690,9 @@ static Scheme_Object *read_compact(CPort *port, int use_stack)
|
|||
port->pos = save_pos;
|
||||
port->symtab[l] = v;
|
||||
}
|
||||
} else if (v == SYMTAB_IN_PROGRESS) {
|
||||
/* there is a cycle */
|
||||
scheme_ill_formed_code(port);
|
||||
}
|
||||
return v;
|
||||
break;
|
||||
|
@ -4983,11 +5001,19 @@ static Scheme_Object *read_compiled(Scheme_Object *port,
|
|||
/* Load table mapping symtab indices to stream positions: */
|
||||
|
||||
all_short = scheme_get_byte(port);
|
||||
so = (intptr_t *)scheme_malloc_fail_ok(scheme_malloc_atomic, sizeof(intptr_t) * symtabsize);
|
||||
if (symtabsize < 0)
|
||||
so = NULL;
|
||||
else
|
||||
so = (intptr_t *)scheme_malloc_fail_ok(scheme_malloc_atomic,
|
||||
scheme_check_overflow(symtabsize, sizeof(intptr_t), 0));
|
||||
if (!so)
|
||||
scheme_read_err(port, NULL, -1, -1, -1, -1, 0, NULL,
|
||||
"read (compiled): could not allocate symbol table of size %" PRIdPTR,
|
||||
symtabsize);
|
||||
if ((got = scheme_get_bytes(port, (all_short ? 2 : 4) * (symtabsize - 1), (char *)so, 0))
|
||||
!= ((all_short ? 2 : 4) * (symtabsize - 1)))
|
||||
scheme_read_err(port, NULL, -1, -1, -1, -1, 0, NULL,
|
||||
"read (compiled): ill-formed code (bad table count: %ld != %ld)",
|
||||
"read (compiled): ill-formed code (bad table count: %" PRIdPTR " != %" PRIdPTR ")",
|
||||
got, (all_short ? 2 : 4) * (symtabsize - 1));
|
||||
offset += got;
|
||||
|
||||
|
@ -5328,6 +5354,8 @@ Scheme_Object *scheme_unmarshal_wrap_get(Scheme_Unmarshal_Tables *ut,
|
|||
|
||||
if ((l < 0) || ((uintptr_t)l >= ut->rp->symtab_size))
|
||||
scheme_ill_formed_code(ut->rp);
|
||||
if (SAME_OBJ(ut->rp->symtab[l], SYMTAB_IN_PROGRESS))
|
||||
scheme_ill_formed_code(ut->rp);
|
||||
|
||||
if (!ut->rp->symtab[l]) {
|
||||
Scheme_Object *v;
|
||||
|
|
|
@ -632,6 +632,17 @@ static void raise_out_of_memory(void)
|
|||
scheme_raise_out_of_memory(NULL, NULL);
|
||||
}
|
||||
|
||||
intptr_t scheme_check_overflow(intptr_t n, intptr_t m, intptr_t a)
|
||||
{
|
||||
intptr_t v;
|
||||
|
||||
v = (n * m) + a;
|
||||
if ((v < n) || (v < m) || (v < a) || (((v - a) / n) != m))
|
||||
scheme_signal_error("allocation size overflow");
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void *scheme_malloc_fail_ok(void *(*f)(size_t), size_t s)
|
||||
{
|
||||
void *v;
|
||||
|
|
|
@ -3663,6 +3663,8 @@ int scheme_can_inline_fp_comp();
|
|||
void scheme_unused_object(Scheme_Object*);
|
||||
void scheme_unused_intptr(intptr_t);
|
||||
|
||||
intptr_t scheme_check_overflow(intptr_t n, intptr_t m, intptr_t a);
|
||||
|
||||
/*========================================================================*/
|
||||
/* places */
|
||||
/*========================================================================*/
|
||||
|
|
|
@ -4723,10 +4723,10 @@ byte_converter_p(int argc, Scheme_Object *argv[])
|
|||
/**********************************************************************/
|
||||
|
||||
static intptr_t utf8_decode_x(const unsigned char *s, intptr_t start, intptr_t end,
|
||||
unsigned int *us, intptr_t dstart, intptr_t dend,
|
||||
intptr_t *ipos, intptr_t *jpos,
|
||||
char compact, char utf16, int *_state,
|
||||
int might_continue, int permissive)
|
||||
unsigned int *us, intptr_t dstart, intptr_t dend,
|
||||
intptr_t *ipos, intptr_t *jpos,
|
||||
char compact, char utf16, int *_state,
|
||||
int might_continue, int permissive)
|
||||
/* Results:
|
||||
non-negative => translation complete, = number of produced chars
|
||||
-1 => input ended in middle of encoding (only if might_continue)
|
||||
|
@ -5079,16 +5079,16 @@ static intptr_t utf8_decode_x(const unsigned char *s, intptr_t start, intptr_t e
|
|||
}
|
||||
|
||||
intptr_t scheme_utf8_decode(const unsigned char *s, intptr_t start, intptr_t end,
|
||||
unsigned int *us, intptr_t dstart, intptr_t dend,
|
||||
intptr_t *ipos, char utf16, int permissive)
|
||||
unsigned int *us, intptr_t dstart, intptr_t dend,
|
||||
intptr_t *ipos, char utf16, int permissive)
|
||||
{
|
||||
return utf8_decode_x(s, start, end, us, dstart, dend,
|
||||
ipos, NULL, utf16, utf16, NULL, 0, permissive);
|
||||
}
|
||||
|
||||
intptr_t scheme_utf8_decode_as_prefix(const unsigned char *s, intptr_t start, intptr_t end,
|
||||
unsigned int *us, intptr_t dstart, intptr_t dend,
|
||||
intptr_t *ipos, char utf16, int permissive)
|
||||
unsigned int *us, intptr_t dstart, intptr_t dend,
|
||||
intptr_t *ipos, char utf16, int permissive)
|
||||
/* Always returns number of read characters, not error codes. */
|
||||
{
|
||||
intptr_t opos;
|
||||
|
|
|
@ -7279,6 +7279,7 @@ static Scheme_Object *datum_to_syntax_inner(Scheme_Object *o,
|
|||
|
||||
--cnt;
|
||||
}
|
||||
if (!first) return_NULL;
|
||||
if (!SCHEME_NULLP(o)) {
|
||||
o = datum_to_syntax_inner(o, ut, stx_src, sub_stx_wraps, ht, tainted);
|
||||
if (!o) return_NULL;
|
||||
|
|
|
@ -793,7 +793,7 @@ static void validate_unclosed_procedure(Mz_CPort *port, Scheme_Object *expr,
|
|||
if (q == self_pos)
|
||||
self_pos_in_closure = i;
|
||||
p = q + delta;
|
||||
if ((q < 0) || (p >= depth) || (stack[p] <= VALID_UNINIT))
|
||||
if ((q < 0) || (p < 0) || (p >= depth) || (stack[p] <= VALID_UNINIT))
|
||||
scheme_ill_formed_code(port);
|
||||
vld = stack[p];
|
||||
if (vld == VALID_VAL_NOCLEAR)
|
||||
|
@ -884,6 +884,10 @@ static void module_validate(Scheme_Object *data, Mz_CPort *port,
|
|||
if (!SCHEME_MODNAMEP(m->modname))
|
||||
scheme_ill_formed_code(port);
|
||||
|
||||
validate_toplevel(m->dummy, port, stack, tls, depth, delta,
|
||||
num_toplevels, num_stxes, num_lifts, tl_use_map,
|
||||
0);
|
||||
|
||||
scheme_validate_code(port, m->bodies[0], m->max_let_depth,
|
||||
m->prefix->num_toplevels, m->prefix->num_stxes, m->prefix->num_lifts,
|
||||
NULL,
|
||||
|
@ -1012,7 +1016,7 @@ void scheme_validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
|
||||
no_flo(need_flonum, port);
|
||||
|
||||
if ((c < 0) || (p < 0) || (d >= depth)
|
||||
if ((c < 0) || (p < 0) || (d < 0) || (d >= depth)
|
||||
|| (stack[d] != VALID_TOPLEVELS)
|
||||
|| (p >= (num_toplevels + num_lifts + num_stxes + (num_stxes ? 1 : 0)))
|
||||
|| ((p >= num_toplevels) && (p < num_toplevels + num_stxes + (num_stxes ? 1 : 0))))
|
||||
|
@ -1071,7 +1075,7 @@ void scheme_validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
int q = SCHEME_LOCAL_POS(expr);
|
||||
int p = q + delta;
|
||||
|
||||
if ((q < 0) || (p >= depth))
|
||||
if ((q < 0) || (p >= depth) || (p < 0))
|
||||
scheme_ill_formed_code(port);
|
||||
|
||||
if (SCHEME_GET_LOCAL_FLAGS(expr) != SCHEME_LOCAL_FLONUM)
|
||||
|
@ -1128,8 +1132,9 @@ void scheme_validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
|
||||
no_flo(need_flonum, port);
|
||||
|
||||
if ((q < 0) || (p >= depth) || ((stack[p] != VALID_BOX)
|
||||
&& (stack[p] != VALID_BOX_NOCLEAR)))
|
||||
if ((q < 0) || (p >= depth) || (p < 0)
|
||||
|| ((stack[p] != VALID_BOX)
|
||||
&& (stack[p] != VALID_BOX_NOCLEAR)))
|
||||
scheme_ill_formed_code(port);
|
||||
|
||||
if (SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_CLEAR_ON_READ) {
|
||||
|
@ -1315,7 +1320,7 @@ void scheme_validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
|
||||
no_flo(need_flonum, port);
|
||||
|
||||
if ((c < 0) || (p < 0) || (d >= depth)
|
||||
if ((c < 0) || (p < 0) || (d < 0) || (d >= depth)
|
||||
|| (stack[d] != VALID_TOPLEVELS)
|
||||
|| (p != num_toplevels)
|
||||
|| (i >= num_stxes))
|
||||
|
@ -1346,6 +1351,7 @@ void scheme_validate_expr(Mz_CPort *port, Scheme_Object *expr,
|
|||
|
||||
for (i = 0; i < c; i++, p++) {
|
||||
if ((q < 0)
|
||||
|| (p < 0)
|
||||
|| (SCHEME_LET_AUTOBOX(lv) && ((p >= depth)
|
||||
|| ((stack[p] != VALID_BOX)
|
||||
&& (stack[p] != VALID_BOX_NOCLEAR))))
|
||||
|
|
Loading…
Reference in New Issue
Block a user