[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" CFLAGS="$CFLAGS -Wno-misleading-indentation"
fi 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, AC_ARG_ENABLE(optimize,
AS_HELP_STRING([--disable-optimize], AS_HELP_STRING([--disable-optimize],
[compile without optimizations (for development)]), [compile without optimizations (for development)]),

View file

@ -63,9 +63,9 @@ bi_va_copy (progs_t *pr, void *data)
if (size) { if (size) {
dst_list_block = PR_AllocTempBlock (pr, size); dst_list_block = PR_AllocTempBlock (pr, size);
dst_list = (pr_type_t *) PR_GetString (pr, dst_list_block); 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).count = src_args->count;
R_PACKED (pr, pr_va_list_t).list = PR_SetPointer (pr, dst_list); 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); 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 static inline void
_set_add_range (set_t *set, unsigned start, unsigned count) _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); set_expand (set, start + count);
} }
unsigned end = start + count - 1; unsigned end = start + count - 1;
set_bits_t start_mask = (~SET_ZERO) << (start % SET_BITS); set_bits_t start_mask = START_MASK (start);
set_bits_t end_mask = (~SET_ZERO) >> (SET_BITS - ((end + 1) % SET_BITS)); set_bits_t end_mask = END_MASK (end);
unsigned start_ind = start / SET_BITS; unsigned start_ind = start / SET_BITS;
unsigned end_ind = end / SET_BITS; unsigned end_ind = end / SET_BITS;
if (start_ind == end_ind) { if (start_ind == end_ind) {
@ -229,8 +234,8 @@ _set_remove_range (set_t *set, unsigned start, unsigned count)
count = set->size - start; count = set->size - start;
} }
unsigned end = start + count - 1; unsigned end = start + count - 1;
set_bits_t start_mask = (~SET_ZERO) << (start % SET_BITS); set_bits_t start_mask = START_MASK (start);
set_bits_t end_mask = (~SET_ZERO) >> (SET_BITS - ((end + 1) % SET_BITS)); set_bits_t end_mask = END_MASK (end);
unsigned start_ind = start / SET_BITS; unsigned start_ind = start / SET_BITS;
unsigned end_ind = end / SET_BITS; unsigned end_ind = end / SET_BITS;
if (start_ind == end_ind) { if (start_ind == end_ind) {

View file

@ -85,6 +85,22 @@ make_range_0_SIZE (void)
return set; 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 * static set_t *
make_range_1_SIZE (void) 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" " 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}" " 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, {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" "{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" " 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; const expr_t *err = 0;
int arg_count = params ? list_count (&params->list) :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) { if (params) {
list_scatter_rev (&params->list, arguments); 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; 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 // params is reversed (a, b, c) -> c, b, a
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
auto e = arguments[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 = new_block_expr (0);
call->block.is_call = 1; call->block.is_call = 1;
int arg_expr_count = 0; 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); expr_t *args = new_list_expr (0);
// args is built in reverse order so it matches params // args is built in reverse order so it matches params
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {

View file

@ -1279,10 +1279,12 @@ flow_build_chains (flowgraph_t *graph)
set_delete (reach.stdef); set_delete (reach.stdef);
graph->func->du_chains = malloc (num_ud_chains * sizeof (udchain_t)); graph->func->du_chains = malloc (num_ud_chains * sizeof (udchain_t));
if (num_ud_chains) {
memcpy (graph->func->du_chains, graph->func->ud_chains, memcpy (graph->func->du_chains, graph->func->ud_chains,
num_ud_chains * sizeof (udchain_t)); num_ud_chains * sizeof (udchain_t));
heapsort (graph->func->du_chains, num_ud_chains, sizeof (udchain_t), heapsort (graph->func->du_chains, num_ud_chains, sizeof (udchain_t),
duchain_cmp); duchain_cmp);
}
for (int i = 0; i < num_ud_chains; i++) { for (int i = 0; i < num_ud_chains; i++) {
udchain_t du = graph->func->du_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.type = ev_func;
type.t.func.num_params = params ? list_count (&params->list) : 0; 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) { if (params) {
list_scatter_rev (&params->list, args); list_scatter_rev (&params->list, args);
} }
@ -384,7 +384,7 @@ find_function (const expr_t *fexpr, const expr_t *params)
return e; 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; type.t.func.param_types = arg_types;
for (int i = 0; i < type.t.func.num_params; i++) { for (int i = 0; i < type.t.func.num_params; i++) {
auto e = args[i]; auto e = args[i];

View file

@ -1183,8 +1183,10 @@ qfo_to_progs (qfo_t *in_qfo, int *size)
// clear locals data // clear locals data
memset (locals, 0, globals_info.locals_size * sizeof (pr_type_t)); memset (locals, 0, globals_info.locals_size * sizeof (pr_type_t));
// copy far data // copy far data
if (qfo->spaces[qfo_far_data_space].data_size) {
memcpy (far_data, qfo->spaces[qfo_far_data_space].data, 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_size * sizeof (pr_type_t));
}
qfo->spaces[qfo_far_data_space].data = far_data; qfo->spaces[qfo_far_data_space].data = far_data;
// copy type data // copy type data
memcpy (type_data, qfo->spaces[qfo_type_space].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); scoped_src_loc (call);
int num_args = list_count (&call->branch.args->list); 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); list_scatter_rev (&call->branch.args->list, args);
int arg_num = 0; int arg_num = 0;
for (int i = 0; i < num_args; i++) { 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; name->type = enum_type;
value = 0; value = 0;
if (enum_tab->symbols) 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) { if (val) {
val = convert_name (val); val = convert_name (val);
if (!is_constant (val)) if (!is_constant (val))