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)