improve ubsan support

Provide `--enable-ubsan` to simplify `-fsanitize=undefined` builds,
where alignment and floating-point divide-by-zero need to be
disabled to get useful results.

Also, repair undefined behavior exposed by the test suite. Most of the
repairs are avoiding `memset(..., NULL, 0)` --- which is an unhelpful
requirement, IMO. The other two repairs are worthwhile but unlikely to
have caused trouble.
This commit is contained in:
Matthew Flatt 2016-10-16 14:48:59 -06:00
parent 153dc01ccd
commit c4d7e8bf1b
17 changed files with 79 additions and 22 deletions

17
racket/src/configure vendored
View File

@ -827,6 +827,7 @@ enable_ffipoll
enable_gprof
enable_gcov
enable_noopt
enable_ubsan
'
ac_precious_vars='build_alias
host_alias
@ -1481,6 +1482,7 @@ Optional Features:
--enable-gcov compile to gather gcov statistics (gcc3 only)
--enable-strip strip debug on install (usually enabled by default)
--enable-noopt drop -O C flags (useful for low-level debugging)
--enable-ubsan compile with -fsanitize=undefined)
Some influential environment variables:
CC C compiler command
@ -2824,6 +2826,11 @@ if test "${enable_noopt+set}" = set; then :
enableval=$enable_noopt;
fi
# Check whether --enable-ubsan was given.
if test "${enable_ubsan+set}" = set; then :
enableval=$enable_ubsan;
fi
###### Some flags imply other flags #######
@ -6791,6 +6798,16 @@ if test "${enable_noopt}" = "yes" ; then
PREFLAGS=`echo "$PREFLAGS" | awk "$AWKPRG"`
fi
############## ubsan ################
if test "${enable_ubsan}" = "yes" ; then
UBSAN="-fsanitize=undefined -fno-sanitize=alignment -fno-sanitize=float-divide-by-zero"
CFLAGS="$CFLAGS $UBSAN"
CPPFLAGS="$CPPFLAGS $UBSAN"
PREFLAGS="$PREFLAGS $UBSAN"
LDFLAGS="$LDFLAGS $UBSAN"
fi
############## usersetup ################
if test "${enable_usersetup}" != "yes" ; then

View File

@ -86,6 +86,7 @@ AC_ARG_ENABLE(gcov, [ --enable-gcov compile to gather gcov statist
AC_ARG_ENABLE(noopt, [ --enable-strip strip debug on install (usually enabled by default)])
AC_ARG_ENABLE(noopt, [ --enable-noopt drop -O C flags (useful for low-level debugging)])
AC_ARG_ENABLE(ubsan, [ --enable-ubsan compile with -fsanitize=undefined)])
###### Some flags imply other flags #######
@ -1629,6 +1630,16 @@ if test "${enable_noopt}" = "yes" ; then
PREFLAGS=`echo "$PREFLAGS" | awk "$AWKPRG"`
fi
############## ubsan ################
if test "${enable_ubsan}" = "yes" ; then
UBSAN="-fsanitize=undefined -fno-sanitize=alignment -fno-sanitize=float-divide-by-zero"
CFLAGS="$CFLAGS $UBSAN"
CPPFLAGS="$CPPFLAGS $UBSAN"
PREFLAGS="$PREFLAGS $UBSAN"
LDFLAGS="$LDFLAGS $UBSAN"
fi
############## usersetup ################
if test "${enable_usersetup}" != "yes" ; then

View File

@ -136,7 +136,8 @@ inline static int create_blank_owner_set(NewGC *gc)
gc->owner_table_size = curr_size;
naya = (OTEntry **)ofm_malloc(curr_size * sizeof(OTEntry*));
memcpy(naya, owner_table, old_size*sizeof(OTEntry*));
if (old_size)
memcpy(naya, owner_table, old_size*sizeof(OTEntry*));
gc->owner_table = owner_table = naya;
bzero(((char*)owner_table) + (sizeof(OTEntry*) * old_size),
(curr_size - old_size) * sizeof(OTEntry*));

View File

@ -17,7 +17,8 @@ static void grow_roots(Roots *roots) {
roots->size = roots->size ? ( 2 * roots->size ) : 500;
new_roots = (uintptr_t *)ofm_malloc(sizeof(uintptr_t) * (roots->size + 1));
memcpy((void *)new_roots, (void *)roots->roots, sizeof(uintptr_t) * roots->count);
if (roots->count)
memcpy((void *)new_roots, (void *)roots->roots, sizeof(uintptr_t) * roots->count);
if (roots->roots)
free(roots->roots);

View File

@ -362,6 +362,10 @@ void exception_thread(void *shared_thread_state)
/* block until we get an exception message */
retval = mach_msg(message, MACH_RCV_MSG, 0, sizeof(mach_exc_msg_t),
exc_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if(retval != KERN_SUCCESS) {
GCPRINT(GCOUTF, "Message receive failed: %s\n", mach_error_string(retval));
abort();
}
/* forward off the handling of this message */
if(!exc_server(message, reply)) {
GCPRINT(GCOUTF, "INTERNAL ERROR: exc_server() didn't like something\n");
@ -370,6 +374,10 @@ void exception_thread(void *shared_thread_state)
/* send the message back out to the thread */
retval = mach_msg(reply, MACH_SEND_MSG, sizeof(mach_reply_msg_t), 0,
MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if(retval != KERN_SUCCESS) {
GCPRINT(GCOUTF, "Message send failed: %s\n", mach_error_string(retval));
abort();
}
}
}

View File

@ -1372,7 +1372,8 @@ static void *realloc_collect_temp(void *v, intptr_t oldsize, intptr_t newsize)
void *naya;
naya = platform_plain_sector((newsize + SECTOR_SEGMENT_SIZE - 1) >> LOG_SECTOR_SEGMENT_SIZE, 0);
memcpy(naya, v, oldsize);
if (oldsize)
memcpy(naya, v, oldsize);
if (v)
munmap(v, (oldsize + SECTOR_SEGMENT_SIZE - 1) >> LOG_SECTOR_SEGMENT_SIZE);

View File

@ -1125,7 +1125,8 @@ void scheme_new_mark_segment(Scheme_Thread *p)
seg = scheme_malloc_allow_interior(sizeof(Scheme_Cont_Mark) * SCHEME_MARK_SEGMENT_SIZE);
segs[c] = seg;
memcpy(segs, p->cont_mark_stack_segments, c * sizeof(Scheme_Cont_Mark *));
if (c)
memcpy(segs, p->cont_mark_stack_segments, c * sizeof(Scheme_Cont_Mark *));
p->cont_mark_seg_count++;
p->cont_mark_stack_segments = segs;

View File

@ -5308,7 +5308,8 @@ static Scheme_Meta_Continuation *clone_meta_cont(Scheme_Meta_Continuation *mc,
} else {
Scheme_Cont_Mark *cp;
cp = MALLOC_N(Scheme_Cont_Mark, naya->cont_mark_total);
memcpy(cp, mc->cont_mark_stack_copied, naya->cont_mark_total * sizeof(Scheme_Cont_Mark));
if (naya->cont_mark_total)
memcpy(cp, mc->cont_mark_stack_copied, naya->cont_mark_total * sizeof(Scheme_Cont_Mark));
clear_cm_copy_caches(cp, naya->cont_mark_total);
naya->cont_mark_stack_copied = cp;
naya->cm_caches = 0;

View File

@ -1248,7 +1248,7 @@ int scheme_generate_flonum_local_unboxing(mz_jit_state *jitter, int push, int no
/*========================================================================*/
#ifdef JIT_PRECISE_GC
static Scheme_Object example_so = { scheme_native_closure_type, 0 };
static struct { Scheme_Object so; int filler; } example_so = { { scheme_native_closure_type, 0}, 0 };
#endif
static Scheme_Native_Lambda *create_native_lambda(Scheme_Lambda *lam, int clear_code_after_jit,

View File

@ -852,7 +852,8 @@ static Scheme_Object *write_lambda(Scheme_Object *obj)
/* Need to grow the array */
Scheme_Object **a;
a = MALLOC_N(Scheme_Object *, (pos ? 2 * pos : 32));
memcpy(a, mt->cdata_map, pos * sizeof(Scheme_Object *));
if (pos)
memcpy(a, mt->cdata_map, pos * sizeof(Scheme_Object *));
mt->cdata_map = a;
}
mt->cdata_counter++;

View File

@ -2677,7 +2677,8 @@ static void register_local_argument_types(Scheme_App_Rec *app, Scheme_App2_Rec *
} else if (predicate_implies(lam->ir_info->arg_types[i], pred)) {
/* widen */
lam->ir_info->arg_types[i] = pred;
lam->ir_info->arg_type_contributors[i] |= (1 << (nth_app-1));
if (nth_app)
lam->ir_info->arg_type_contributors[i] |= (1 << (nth_app-1));
} else
widen_to_top = 1;
} else

View File

@ -665,7 +665,8 @@ string_write_bytes(Scheme_Output_Port *port,
memcpy(is->string, old, is->index);
}
memcpy(is->string + is->index, str + d, len);
if (len)
memcpy(is->string + is->index, str + d, len);
is->index += len;
return len;

View File

@ -1235,7 +1235,8 @@ static void print_this_string(PrintParams *pp, const char *str, int offset, int
memcpy(pp->print_buffer, oldstr, pp->print_position);
}
memcpy(pp->print_buffer + pp->print_position, str + offset, len);
if (len)
memcpy(pp->print_buffer + pp->print_position, str + offset, len);
pp->print_position += len;
pp->print_offset += len;
@ -4144,7 +4145,8 @@ void scheme_set_type_printer(Scheme_Type stype, Scheme_Type_Printer printer)
Scheme_Type_Printer *naya;
naya = MALLOC_N(Scheme_Type_Printer, stype + 10);
memset(naya, 0, sizeof(Scheme_Type_Printer) * (stype + 10));
memcpy(naya, printers, sizeof(Scheme_Type_Printer) * printers_count);
if (printers_count)
memcpy(naya, printers, sizeof(Scheme_Type_Printer) * printers_count);
printers_count = stype + 10;
printers = naya;
}

View File

@ -2448,7 +2448,8 @@ static void stack_room(Regwork *rw, int amt)
sz = rw->rewind_stack_size * 2;
if (!sz) sz = MATCH_STACK_SIZE;
p = (rxpos *)scheme_malloc_atomic(sizeof(rxpos)*sz);
memcpy(p, rw->rewind_stack, rw->rewind_stack_size * sizeof(rxpos));
if (rw->rewind_stack_size)
memcpy(p, rw->rewind_stack, rw->rewind_stack_size * sizeof(rxpos));
rw->rewind_stack = p;
rw->rewind_stack_size = sz;
}
@ -2964,7 +2965,8 @@ static void read_more_from_lazy_string(Regwork *rw, rxpos need_total)
0 /* not UTF-16 */);
tlen = blen + ls->blen;
s = (char *)scheme_malloc_atomic(tlen);
memcpy(s, ls->s, ls->blen);
if (ls->blen)
memcpy(s, ls->s, ls->blen);
scheme_utf8_encode(ls->chars, ls->start + ls->done, ls->start + ls->done + amt,
(unsigned char *)s, ls->blen,
0 /* not UTF-16 */);
@ -3012,7 +3014,8 @@ static void read_more_from_regport(Regwork *rw, rxpos need_total)
size = 16;
naya = (char *)scheme_malloc_atomic(size);
memcpy(naya, rw->instr, rw->input_end);
if (rw->input_end)
memcpy(naya, rw->instr, rw->input_end);
rw->instr = naya;
rw->instr_size = size;
@ -5916,7 +5919,8 @@ static Scheme_Object *gen_replace(const char *name, int argc, Scheme_Object *arg
total = len + prefix_len + (startpd - srcoffset);
naya = (char *)scheme_malloc_atomic(total + more + 1);
memcpy(naya, prefix, prefix_len);
if (prefix_len)
memcpy(naya, prefix, prefix_len);
memcpy(naya + prefix_len, source + srcoffset, startpd - srcoffset);
memcpy(naya + prefix_len + (startpd - srcoffset), insert, len);
if (more) {

View File

@ -4697,11 +4697,13 @@ static Scheme_Object *make_name(const char *pre, const char *tn, int ltn,
memcpy(name, pre, lp);
total = lp;
memcpy(name + total, (ltn < 0) ? SCHEME_SYM_VAL((Scheme_Object *)tn) : tn, xltn);
if (xltn)
memcpy(name + total, (ltn < 0) ? SCHEME_SYM_VAL((Scheme_Object *)tn) : tn, xltn);
total += xltn;
memcpy(name + total, post1, lp1);
total += lp1;
memcpy(name + total, (lfn < 0) ? SCHEME_SYM_VAL((Scheme_Object *)fn) : fn, xlfn);
if (xlfn)
memcpy(name + total, (lfn < 0) ? SCHEME_SYM_VAL((Scheme_Object *)fn) : fn, xlfn);
total += xlfn;
memcpy(name + total, post2, lp2);
total += lp2;
@ -5092,7 +5094,8 @@ static Scheme_Object *_make_struct_type(Scheme_Object *base,
}
pa = MALLOC_N(Scheme_Object *, i + num_props);
memcpy(pa, struct_type->props, sizeof(Scheme_Object *) * i);
if (i)
memcpy(pa, struct_type->props, sizeof(Scheme_Object *) * i);
num_props = i;

View File

@ -1720,7 +1720,8 @@ static Scheme_Object *make_custodian_box(int argc, Scheme_Object *argv[])
cust_box_alloc = 2 * cust_box_alloc;
}
cbs = (Scheme_Custodian_Box **)scheme_malloc_atomic(cust_box_alloc * sizeof(Scheme_Custodian_Box *));
memcpy(cbs, cust_boxes, cust_box_count * sizeof(Scheme_Custodian_Box *));
if (cust_box_count)
memcpy(cbs, cust_boxes, cust_box_count * sizeof(Scheme_Custodian_Box *));
cust_boxes = cbs;
}
cust_boxes[cust_box_count++] = cb;
@ -6284,7 +6285,8 @@ void scheme_add_evt_worker(Evt ***evt_array,
if (new_size < _scheme_last_type_)
new_size = _scheme_last_type_;
nevts = MALLOC_N(Evt*, new_size);
memcpy(nevts, (*evt_array), (*evt_size) * sizeof(Evt*));
if (*evt_size)
memcpy(nevts, (*evt_array), (*evt_size) * sizeof(Evt*));
(*evt_array) = nevts;
(*evt_size) = new_size;
}

View File

@ -99,7 +99,8 @@ static void clearing_stack_push(struct Validate_Clearing *vc, int pos, int val)
int *a, sz;
sz = (vc->stacksize ? 2 * vc->stacksize : 32);
a = (int *)scheme_malloc_atomic(sizeof(int) * sz);
memcpy(a, vc->stack, vc->stacksize * sizeof(int));
if (vc->stacksize)
memcpy(a, vc->stack, vc->stacksize * sizeof(int));
vc->stacksize = sz;
vc->stack = a;
}
@ -114,7 +115,8 @@ static void noclear_stack_push(struct Validate_Clearing *vc, int pos)
int *a, sz;
sz = (vc->ncstacksize ? 2 * vc->ncstacksize : 32);
a = (int *)scheme_malloc_atomic(sizeof(int) * sz);
memcpy(a, vc->ncstack, vc->ncstacksize * sizeof(int));
if (vc->ncstacksize)
memcpy(a, vc->ncstack, vc->ncstacksize * sizeof(int));
vc->ncstacksize = sz;
vc->ncstack = a;
}