https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65029
Bug ID: 65029 Summary: aggregate copy invokes memcpy on overlapping regions Product: gcc Version: 4.9.2 Status: UNCONFIRMED Severity: minor Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gmail dot com According to 7.24.2.1 of C11, "If copying takes place between objects that overlap, the behavior [of memcpy] is undefined." The script below shows that GCC generates code with undefined behavior for a strictly conforming C11 program (the code is the same with -fno-builtin-memcpy or -ffreestanding). This was brought to light by the valgrind error (also shown). $ cat t.c && gcc -DMEMCPY -DN=65 -O2 -Wall -std=c11 t.c && ./a.out || gcc -DN=65 -O2 -Wall -std=c11 t.c && valgrind ./a.out #include <assert.h> #include <stddef.h> struct S { char c [N]; }; void __attribute__ ((weak)) foo (struct S *a, struct S *b) { *a = *b; } #if MEMCPY void* memcpy (void* restrict d, const void* restrict s, size_t n) { typedef unsigned char UChar; UChar *pd; const UChar *ps; assert (d != s); for (pd = (UChar*)d, ps = (const UChar*)s; n--; ++pd, ++ps) *pd = *ps; return d; } #endif int main (void) { struct S s = { { 0 } }; foo (&s, &s); return 0; } a.out: t.c:22: memcpy: Assertion `d != s' failed. Aborted ==62960== Memcheck, a memory error detector ==62960== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==62960== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info ==62960== Command: ./a.out ==62960== ==62960== Source and destination overlap in memcpy(0xfff00eb30, 0xfff00eb30, 65) ==62960== at 0x408C908: memcpy (in /usr/lib64/valgrind/vgpreload_memcheck-ppc64be-linux.so) ==62960== by 0x10000643: foo (in /home/remote/msebor/tmp/a.out) ==62960== by 0x10000433: main (in /home/remote/msebor/tmp/a.out) ==62960== ==62960== ==62960== HEAP SUMMARY: ==62960== in use at exit: 0 bytes in 0 blocks ==62960== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==62960== ==62960== All heap blocks were freed -- no leaks are possible ==62960== ==62960== For counts of detected and suppressed errors, rerun with: -v ==62960== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)