https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108296
Bug ID: 108296
Summary: __builtin_memcpy generating wrong code in some cases
Product: gcc
Version: 12.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: nyh at math dot technion.ac.il
Target Milestone: ---
The following trivial code, copying a string over itself moved by one byte,
shows wrong results for __builtin_memcpy() on gcc 12.2.1:
#include <cstring>
int main(){
char bufa[128] = "0123456789abcdefghijklmnopqrstuvwxyz";
char bufb[128] = "0123456789abcdefghijklmnopqrstuvwxyz";
memcpy(bufa, bufa+1, 27);
printf(" memcpy: %s\n", bufa);
__builtin_memcpy(bufb, bufb+1, 27);
printf("__builtin_memcpy: %s\n", bufb);
}
As you can see running it, memcpy() returned the right result,
123456789abcdefghijklmnopqrrstuvwxyz (the first 27 characters shifted back, so
"r" is double in the response), but __builtin_memcpy() returned the *wrong*
result - 123456789abdefgghijklmnopqrrstuvwxyz (the "c" character disappeared
and the "g" is also doubled).
This bug was discovered in the OSv project
https://github.com/cloudius-systems/osv/issues/1212 with code that doesn't
(obviously) call __builtin_memcpy() directly, but rather had a 27-character
type being copied and the compiler implemented this copy with a call to
__builtin_memcpy(). The original miscompiling code in OSv was something like
the following:
#include <cstdio>
int main(){
char buf[128] = "0123456789abcdefghijklmnopqrstuvwxyz";
struct [[gnu::packed]] data {
char x[27];
};
void *p0 = buf;
void *p1 = &buf[1];
*static_cast<data*>(p0) = *static_cast<const data*>(p1);
printf("%s", buf);
}
This appears to be a regression - this code did not miscompile in earlier gcc
releases.