[build] Add an option to enable ubsan

It's disabled by default because it's a runtime thing and I'm not sure I
want to keep it enabled, but it did find some issues (which I've cleaned
up), although it didn't find the problem I was looking for :P
This commit is contained in:
Bill Currie 2024-02-21 21:39:07 +09:00
parent 073c93eebf
commit 925dba732c
10 changed files with 73 additions and 18 deletions

View file

@ -111,6 +111,20 @@ if test "x$CLANG" = xyes -a "x$leave_cflags_alone" != xyes; then
CFLAGS="$CFLAGS -Wno-misleading-indentation"
fi
AC_ARG_ENABLE(ubsan,
AS_HELP_STRING([--enable-ubsan],
[compile with ubsan (for development)]),
ubsan=$enable_ubsan,
ubsan=no
)
if test "x$ubsan" = xyes -a "x$leave_cflags_alone" != "xyes"; then
QF_CC_OPTION(-fsanitize=undefined)
QF_CC_OPTION_TEST([-fsanitize=undefined], [
CFLAGS="$CFLAGS -fsanitize=undefined"
CXXFLAGS="$CXXFLAGS -fsanitize=undefined"
])
fi
AC_ARG_ENABLE(optimize,
AS_HELP_STRING([--disable-optimize],
[compile without optimizations (for development)]),

View file

@ -63,9 +63,9 @@ bi_va_copy (progs_t *pr, void *data)
if (size) {
dst_list_block = PR_AllocTempBlock (pr, size);
dst_list = (pr_type_t *) PR_GetString (pr, dst_list_block);
memcpy (dst_list, src_list, size);
}
memcpy (dst_list, src_list, size);
R_PACKED (pr, pr_va_list_t).count = src_args->count;
R_PACKED (pr, pr_va_list_t).list = PR_SetPointer (pr, dst_list);
}

View file

@ -191,6 +191,11 @@ _set_remove (set_t *set, unsigned x)
SET_REMOVE(set, x);
}
#define START_MASK(start) \
((~SET_ZERO) << (start % SET_BITS))
#define END_MASK(end) \
((~SET_ZERO) >> ((SET_BITS - ((end + 1) % SET_BITS)) % SET_BITS))
static inline void
_set_add_range (set_t *set, unsigned start, unsigned count)
{
@ -201,8 +206,8 @@ _set_add_range (set_t *set, unsigned start, unsigned count)
set_expand (set, start + count);
}
unsigned end = start + count - 1;
set_bits_t start_mask = (~SET_ZERO) << (start % SET_BITS);
set_bits_t end_mask = (~SET_ZERO) >> (SET_BITS - ((end + 1) % SET_BITS));
set_bits_t start_mask = START_MASK (start);
set_bits_t end_mask = END_MASK (end);
unsigned start_ind = start / SET_BITS;
unsigned end_ind = end / SET_BITS;
if (start_ind == end_ind) {
@ -229,8 +234,8 @@ _set_remove_range (set_t *set, unsigned start, unsigned count)
count = set->size - start;
}
unsigned end = start + count - 1;
set_bits_t start_mask = (~SET_ZERO) << (start % SET_BITS);
set_bits_t end_mask = (~SET_ZERO) >> (SET_BITS - ((end + 1) % SET_BITS));
set_bits_t start_mask = START_MASK (start);
set_bits_t end_mask = END_MASK (end);
unsigned start_ind = start / SET_BITS;
unsigned end_ind = end / SET_BITS;
if (start_ind == end_ind) {

View file

@ -85,6 +85,22 @@ make_range_0_SIZE (void)
return set;
}
static set_t *
make_range_0_SIZEm1 (void)
{
set_t *set = set_new ();
set_add_range (set, 0, SIZE - 1);
return set;
}
static set_t *
make_range_0_SIZEx2 (void)
{
set_t *set = set_new ();
set_add_range (set, 0, SIZE*2);
return set;
}
static set_t *
make_range_1_SIZE (void)
{
@ -302,6 +318,22 @@ struct {
" 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47"
" 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63}"
},
{make_range_0_SIZEm1, 0, 0, check_size, SIZE,
"{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
" 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
" 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47"
" 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62}"
},
{make_range_0_SIZEx2, 0, 0, check_size, SIZE*2,
"{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
" 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
" 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47"
" 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63"
" 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79"
" 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95"
" 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111"
" 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127}"
},
{make_range_1_SIZE, 0, 0, check_size, SIZE + SET_BITS,
"{1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
" 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"

View file

@ -2105,7 +2105,7 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
const expr_t *err = 0;
int arg_count = params ? list_count (&params->list) :0;
const expr_t *arguments[arg_count];
const expr_t *arguments[arg_count + 1];
if (params) {
list_scatter_rev (&params->list, arguments);
}
@ -2145,7 +2145,7 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
param_count = ftype->t.func.num_params;
}
const type_t *arg_types[arg_count];
const type_t *arg_types[arg_count + 1];
// params is reversed (a, b, c) -> c, b, a
for (int i = 0; i < arg_count; i++) {
auto e = arguments[i];
@ -2224,7 +2224,7 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
call = new_block_expr (0);
call->block.is_call = 1;
int arg_expr_count = 0;
const expr_t *arg_exprs[arg_count][2];
const expr_t *arg_exprs[arg_count + 1][2];
expr_t *args = new_list_expr (0);
// args is built in reverse order so it matches params
for (int i = 0; i < arg_count; i++) {

View file

@ -1279,10 +1279,12 @@ flow_build_chains (flowgraph_t *graph)
set_delete (reach.stdef);
graph->func->du_chains = malloc (num_ud_chains * sizeof (udchain_t));
memcpy (graph->func->du_chains, graph->func->ud_chains,
num_ud_chains * sizeof (udchain_t));
heapsort (graph->func->du_chains, num_ud_chains, sizeof (udchain_t),
duchain_cmp);
if (num_ud_chains) {
memcpy (graph->func->du_chains, graph->func->ud_chains,
num_ud_chains * sizeof (udchain_t));
heapsort (graph->func->du_chains, num_ud_chains, sizeof (udchain_t),
duchain_cmp);
}
for (int i = 0; i < num_ud_chains; i++) {
udchain_t du = graph->func->du_chains[i];

View file

@ -373,7 +373,7 @@ find_function (const expr_t *fexpr, const expr_t *params)
type.type = ev_func;
type.t.func.num_params = params ? list_count (&params->list) : 0;
const expr_t *args[type.t.func.num_params];
const expr_t *args[type.t.func.num_params + 1];
if (params) {
list_scatter_rev (&params->list, args);
}
@ -384,7 +384,7 @@ find_function (const expr_t *fexpr, const expr_t *params)
return e;
}
}
const type_t *arg_types[type.t.func.num_params];
const type_t *arg_types[type.t.func.num_params + 1];
type.t.func.param_types = arg_types;
for (int i = 0; i < type.t.func.num_params; i++) {
auto e = args[i];

View file

@ -1183,8 +1183,10 @@ qfo_to_progs (qfo_t *in_qfo, int *size)
// clear locals data
memset (locals, 0, globals_info.locals_size * sizeof (pr_type_t));
// copy far data
memcpy (far_data, qfo->spaces[qfo_far_data_space].data,
qfo->spaces[qfo_far_data_space].data_size * sizeof (pr_type_t));
if (qfo->spaces[qfo_far_data_space].data_size) {
memcpy (far_data, qfo->spaces[qfo_far_data_space].data,
qfo->spaces[qfo_far_data_space].data_size * sizeof (pr_type_t));
}
qfo->spaces[qfo_far_data_space].data = far_data;
// copy type data
memcpy (type_data, qfo->spaces[qfo_type_space].data,

View file

@ -1174,7 +1174,7 @@ expr_call (sblock_t *sblock, const expr_t *call, operand_t **op)
scoped_src_loc (call);
int num_args = list_count (&call->branch.args->list);
const expr_t *args[num_args];
const expr_t *args[num_args + 1];
list_scatter_rev (&call->branch.args->list, args);
int arg_num = 0;
for (int i = 0; i < num_args; i++) {

View file

@ -284,7 +284,7 @@ add_enum (symbol_t *enm, symbol_t *name, const expr_t *val)
name->type = enum_type;
value = 0;
if (enum_tab->symbols)
value = ((symbol_t *)(enum_tab->symtail))->s.value->v.int_val + 1;
value = ((symbol_t *)(enum_tab->symtail))->s.value->v.uint_val + 1;
if (val) {
val = convert_name (val);
if (!is_constant (val))