Testing my patch to warn on overflow in calls to allocation functions (bugs 77531 and 78284):
https://gcc.gnu.org/ml/gcc-patches/2016-11/msg01672.html exposed a number of instances of alloca(0) calls in GCC sources. Besides this patch which enables the new warnings with -Wextra (the patch is still in the review queue) the same code also triggers a -Walloca-larger-than warning (which has to be explicitly enabled). It doesn't look to me like these calls are bugs per se but in the interest of eating our own dog food so to speak and being able to compile GCC with -Walloca-larger-than (and not to have to disable the yet-to-be committed -Walloc-zero warning) the attached patch makes sure that the alloca calls that are subject to the warnings always request at least 1 byte. Thanks Martin PS Alloca(0) is not necessarily undefined but the pointer the call returns need not be distinct from other pointers returned from other such calls in the same function (and there are compilers that do not make it distinct). Relying on the pointer being distinct could be a source of subtle bugs, hence the warning.
gcc/fortran/ChangeLog: * interface.c (compare_actual_formal): Avoid calling alloca with an argument of zero. * symbol.c (do_traverse_symtree): Same. * trans-intrinsic.c (gfc_conv_intrinsic_ishftc): Same. gcc/ChangeLog: * reg-stack.c (subst_asm_stack_regs): Same. * tree-ssa-threadedge.c (record_temporary_equivalences_from_stmts_at_dest): Same. diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index a0cb0bb..2da51d7 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -2821,7 +2821,8 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal, for (f = formal; f; f = f->next) n++; - new_arg = XALLOCAVEC (gfc_actual_arglist *, n); + /* Take care not to call alloca with a zero argument. */ + new_arg = XALLOCAVEC (gfc_actual_arglist *, n + !n); for (i = 0; i < n; i++) new_arg[i] = NULL; diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 0b711ca..cf403c4 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -3979,7 +3979,8 @@ do_traverse_symtree (gfc_symtree *st, void (*st_func) (gfc_symtree *), gcc_assert ((st_func && !sym_func) || (!st_func && sym_func)); nodes = count_st_nodes (st); - st_vec = XALLOCAVEC (gfc_symtree *, nodes); + /* Take care not to call alloca with a zero argument. */ + st_vec = XALLOCAVEC (gfc_symtree *, nodes + !nodes); node_cntr = 0; fill_st_vector (st, st_vec, node_cntr); diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 463bb58..e4715f8 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -5525,7 +5525,8 @@ gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr) unsigned int num_args; num_args = gfc_intrinsic_argument_list_length (expr); - args = XALLOCAVEC (tree, num_args); + /* Take care not to call alloca with a zero argument. */ + args = XALLOCAVEC (tree, num_args + !num_args); gfc_conv_intrinsic_function_args (se, expr, args, num_args); diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 4e86fa9..7da5a5f 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -2050,9 +2050,10 @@ subst_asm_stack_regs (rtx_insn *insn, stack_ptr regstack) for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1)) i++; - note_reg = XALLOCAVEC (rtx, i); - note_loc = XALLOCAVEC (rtx *, i); - note_kind = XALLOCAVEC (enum reg_note, i); + /* Take care not to call alloca with a zero argument. */ + note_reg = XALLOCAVEC (rtx, i + !i); + note_loc = XALLOCAVEC (rtx *, i + !i); + note_kind = XALLOCAVEC (enum reg_note, i + !i); n_notes = 0; for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 534292c..0564e69 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -340,7 +340,8 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, unsigned int num, i = 0; num = NUM_SSA_OPERANDS (stmt, SSA_OP_ALL_USES); - copy = XALLOCAVEC (tree, num); + /* Take care not to call alloca with a zero argument. */ + copy = XALLOCAVEC (tree, num + !num); /* Make a copy of the uses & vuses into USES_COPY, then cprop into the operands. */