This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Infinite loop or abort on malformed C
- To: egcs-bugs at egcs dot cygnus dot com
- Subject: Infinite loop or abort on malformed C
- From: Zack Weinberg <zack at rabi dot columbia dot edu>
- Date: Fri, 16 Apr 1999 09:33:49 -0400
This fragment
typedef int word_type;
static void
copy_reg (unsigned int reg, frame_state *udata, frame_state *target_udata)
{
word_type *preg = get_reg_addr (reg, udata, 0);
word_type *ptreg = get_reg_addr (reg, target_udata, 0);
memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
}
sends the current development tree into a near-infinite loop,
eventually running out of memory and dying with SIGBUS. 1.1.x is a
bit more polite, it just ICEs:
copy_reg.i:4: parse error before `frame_state'
copy_reg.i: In function `copy_reg':
copy_reg.i:6: `reg' undeclared (first use in this function)
copy_reg.i:6: `udata' undeclared (first use in this function)
copy_reg.i:6: warning: initialization makes pointer from integer without a cast
copy_reg.i:7: `target_udata' undeclared (first use in this function)
copy_reg.i:7: warning: initialization makes pointer from integer without a cast
../../gcc/expr.c:2568: Internal compiler error in function emit_move_insn_1
The problem is that force_reg is called with mode=226
(MAX_MACHINE_MODE is 33). The loop in emit_move_insn_1
2657 for (i = 0;
2658 i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1))
/ UNITS_PER_WORD;
2659 i++)
tries to iterate (mode_size[226]+3) / 4 times. This happens to be a
very large number. We try to allocate something like 34 million insns
and run out of memory. Adding an
if (mode >= MAX_MACHINE_MODE)
abort();
to the very beginning of force_reg gets us an ICE again instead of an
infinite loop. (This could equally go right before the loop in
emit_move_insn_1.)
The bogus mode came from compare (in expr.c). Its EXP argument
contains an error_mark:
(gdb) p exp
$6 = 0x828f7d8
(gdb) pt
<gt_expr 0x828f7d8
type <integer_type 0x828de98 int allocated from permanent_obstack
permanent SI
size <integer_cst 0x828e078 constant permanent 32>
align 32 symtab 0 alias set -1 precision 32
min <integer_cst 0x828def8 constant permanent -2147483648>
max <integer_cst 0x828df10 constant permanent 2147483647>
pointer_to_this <pointer_type 0x8294304>>
allocated from momentary_obstack
arg 0 <error_mark 0x8292d98>
arg 1 <integer_cst 0x828f7c0 type <integer_type 0x828de98 int> constant 10>>
mode is set to TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), which is
garbage. compare needs to check for an error_mark in that position
and do something sensible - I don't know what that would be.
Alternatively, the parser could be changed to treat `something *',
where `something' is an unknown symbol, as `void *' for purposes of
error recovery.
zw