http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48758
Summary: gcc miscompiles Emacs by incorrectly substituting memcpy for memmove Product: gcc Version: 4.6.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: egg...@gnu.org Host: i686-pc-linux-gnu Target: i686-pc-linux-gnu Build: i686-pc-linux-gnu Created attachment 24094 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=24094 Copy of the source code illustrating the problem When compiling a test version of GNU Emacs with GCC 4.6.0 on Ubuntu 10.10 x86, the resulting Emacs usually works, but sometimes it crashes. It took me a while to debug the problem, but it turns out that GCC 4.6.0 incorrectly substitutes memcpy for memmove, and this invalid substitution crashes Emacs. This is a regression from the GCC 4.4.5 that comes with Ubuntu. Here's a stripped-down source file c.c illustrating the problem; (I've also attached c.c for convenience.) typedef unsigned int size_t; extern void *memmove (void *__dest, __const void *__src, size_t __n) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__artificial__)) void * __attribute__ ((__nothrow__)) memmove (void *__restrict __dest, __const void *__restrict __src, size_t __len) { return __builtin___memmove_chk (__dest, __src, __len, __builtin_object_size (__dest, 0)); } void str_to_multibyte (unsigned char *str, int len, int bytes) { unsigned char *p = str, *endp = str + bytes; while (p < endp && *p < 0x80) p++; if (p == endp) return; bytes = endp - p; endp = str + len; memmove (endp - bytes, p, bytes); } Here's the assembly language output from running 'gcc -S -O2'. Notice that it invokes memcpy, not memmove. But this is an invalid optimization, because 'bytes' and 'len' are independent, and it could well be that the target of memmove overlaps the source. .file "c.c" .text .p2align 4,,15 .globl str_to_multibyte .type str_to_multibyte, @function str_to_multibyte: .LFB1: .cfi_startproc pushl %esi .cfi_def_cfa_offset 8 .cfi_offset 6, -8 pushl %ebx .cfi_def_cfa_offset 12 .cfi_offset 3, -12 movl 12(%esp), %ebx movl 20(%esp), %ecx movl 16(%esp), %esi addl %ebx, %ecx cmpl %ecx, %ebx jae .L2 cmpb $0, (%ebx) movl %ebx, %edx jns .L4 jmp .L2 .p2align 4,,7 .p2align 3 .L9: cmpb $0, 1(%edx) js .L6 movl %eax, %edx .L4: leal 1(%edx), %eax cmpl %ecx, %eax jne .L9 .L1: popl %ebx .cfi_remember_state .cfi_def_cfa_offset 8 .cfi_restore 3 popl %esi .cfi_def_cfa_offset 4 .cfi_restore 6 ret .L2: .cfi_restore_state cmpl %ecx, %ebx je .L1 movl %ebx, %eax .p2align 4,,7 .p2align 3 .L6: subl %eax, %ecx addl %esi, %ebx subl %ecx, %ebx movl %ecx, 20(%esp) movl %eax, 16(%esp) movl %ebx, 12(%esp) popl %ebx .cfi_def_cfa_offset 8 .cfi_restore 3 popl %esi .cfi_def_cfa_offset 4 .cfi_restore 6 jmp memcpy .cfi_endproc .LFE1: .size str_to_multibyte, .-str_to_multibyte .ident "GCC: (GNU) 4.6.0" .section .note.GNU-stack,"",@progbits Here's the output of 'gcc -v -save-temps -S -O2 c.c': Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/home/eggert/opt/gcc-4.6.0/libexec/gcc/i686-pc-linux-gnu/4.6.0/lto-wrapper Target: i686-pc-linux-gnu Configured with: ../gcc-4.6.0/configure --prefix=/home/eggert/opt/gcc-4.6.0 --disable-nls Thread model: posix gcc version 4.6.0 (GCC) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-S' '-O2' '-mtune=generic' '-march=pentiumpro' /home/eggert/opt/gcc-4.6.0/libexec/gcc/i686-pc-linux-gnu/4.6.0/cc1 -E -quiet -v c.c -mtune=generic -march=pentiumpro -O2 -fpch-preprocess -o c.i ignoring nonexistent directory "/home/eggert/opt/gcc-4.6.0/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../../i686-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /home/eggert/opt/gcc-4.6.0/lib/gcc/i686-pc-linux-gnu/4.6.0/include /usr/local/include /home/eggert/opt/gcc-4.6.0/include /home/eggert/opt/gcc-4.6.0/lib/gcc/i686-pc-linux-gnu/4.6.0/include-fixed /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-S' '-O2' '-mtune=generic' '-march=pentiumpro' /home/eggert/opt/gcc-4.6.0/libexec/gcc/i686-pc-linux-gnu/4.6.0/cc1 -fpreprocessed c.i -quiet -dumpbase c.c -mtune=generic -march=pentiumpro -auxbase c -O2 -version -o c.s GNU C (GCC) version 4.6.0 (i686-pc-linux-gnu) compiled by GNU C version 4.6.0, GMP version 4.3.2, MPFR version 3.0.0-p3, MPC version 0.8.2 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C (GCC) version 4.6.0 (i686-pc-linux-gnu) compiled by GNU C version 4.6.0, GMP version 4.3.2, MPFR version 3.0.0-p3, MPC version 0.8.2 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: fb2445fcd60a2e52fefc7ee16750c6b7 COMPILER_PATH=/home/eggert/opt/gcc-4.6.0/libexec/gcc/i686-pc-linux-gnu/4.6.0/:/home/eggert/opt/gcc-4.6.0/libexec/gcc/i686-pc-linux-gnu/4.6.0/:/home/eggert/opt/gcc-4.6.0/libexec/gcc/i686-pc-linux-gnu/:/home/eggert/opt/gcc-4.6.0/lib/gcc/i686-pc-linux-gnu/4.6.0/:/home/eggert/opt/gcc-4.6.0/lib/gcc/i686-pc-linux-gnu/ LIBRARY_PATH=/home/eggert/opt/gcc-4.6.0/lib/gcc/i686-pc-linux-gnu/4.6.0/:/home/eggert/opt/gcc-4.6.0/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-S' '-O2' '-mtune=generic' '-march=pentiumpro'