Even with PR89427 resolved, GCC still fails to detect the invalid accesses in the functions below (_FORTIFY_SOURCE doesn't help because it doesn't try to detect sizes from pointers involving variable offsets): $ cat x.c && gcc -O2 -S -Wall x.c char a[2]; void f (int i, const char *s) { if (i < 1 || 2 < i) i = 1; char *p = &a[i] - 9; __builtin_memcpy (p, s, 2); // writing before the beginning of a } void g (int i, const char *s) { if (i < 1 || 2 < i) i = 1; char *p = &a[i] + 9; __builtin_memcpy (p, s, 2); // writing past the end of a }
I'm testing a patch that diagnoses this.
Fixed in GCC 10 via r279248 which now prints: pr92307.c: In function ‘f’: pr92307.c:2:3: warning: writing 2 bytes into a region of size 1 [-Wstringop-overflow=] 2 | __builtin_memcpy (d, s, n) | ^~~~~~~~~~~~~~~~~~~~~~~~~~ pr92307.c:10:3: note: in expansion of macro ‘memcpy’ 10 | memcpy (p, s, 2); // writing before the beginning of a | ^~~~~~ pr92307.c:4:6: note: at offset 0 to object ‘a’ with size 2 declared here 4 | char a[2]; | ^ pr92307.c: In function ‘g’: pr92307.c:2:3: warning: writing 2 bytes into a region of size 0 [-Wstringop-overflow=] 2 | __builtin_memcpy (d, s, n) | ^~~~~~~~~~~~~~~~~~~~~~~~~~ pr92307.c:17:3: note: in expansion of macro ‘memcpy’ 17 | memcpy (p, s, 2); // writing past the end of a | ^~~~~~ pr92307.c:4:6: note: at offset 0 to object ‘a’ with size 2 declared here 4 | char a[2]; | ^