https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65114
Bug ID: 65114 Summary: char_traits::copy violates memcpy constraints, own postcondition Product: gcc Version: 4.9.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gmail dot com The precondition on char_traits::copy(s, p, n), namely that p not be in the range [s, s + n), is weaker than the precondition on a call to memcpy(s, p, n). The latter requires that none of the characters accessed via s is also accessed via p. The program below shows an example of a call to char_traits<char>::copy that satisfies the C++ precondition but violates the C precondition (as indicated by the Valgrind error). The element a[1] is accessed by both s and p. As a result, the program also fails the C++ postcondition. $ cat t.cpp && g++ -Wall t.cpp && valgrind ./a.out #include <assert.h> #include <stdio.h> #include <string> struct Traits: std::char_traits<char> { static char* copy (char *s, const char *p, size_t n) { assert (p < s || s + n < p); return std::char_traits<char>::copy (s, p, n); } }; int main () { char a[] = "abc"; const size_t n = 2; const char *p = a; char *s = a + 1; for (size_t i = 0; i != n; ++i) Traits::assign (s[i], p[i]); char b[] = "abc"; p = b; s = b + 1; Traits::copy (s, p, n); printf ("%s == %s\n", a, b); assert (0 == Traits::compare (a, b, sizeof a)); } ==15497== Memcheck, a memory error detector ==15497== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==15497== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==15497== Command: ./a.out ==15497== ==15497== Source and destination overlap in memcpy(0xffefffe41, 0xffefffe40, 2) ==15497== at 0x4C2E13D: memcpy@@GLIBC_2.14 (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==15497== by 0x400859: std::char_traits<char>::copy(char*, char const*, unsigned long) (in /home/msebor/tmp/a.out) ==15497== by 0x4008BA: Traits::copy(char*, char const*, unsigned long) (in /home/msebor/tmp/a.out) ==15497== by 0x40078A: main (in /home/msebor/tmp/a.out) ==15497== aaa == aab a.out: t.cpp:30: int main(): Assertion `0 == Traits::compare (a, b, sizeof a)' failed. ==15497== ==15497== HEAP SUMMARY: ==15497== in use at exit: 0 bytes in 0 blocks ==15497== total heap usage: 2 allocs, 2 frees, 188 bytes allocated ==15497== ==15497== All heap blocks were freed -- no leaks are possible ==15497== ==15497== For counts of detected and suppressed errors, rerun with: -v ==15497== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) Aborted (core dumped)