Summary: | missing warning on buffer overflow storing a larger scalar into a smaller array | ||
---|---|---|---|
Product: | gcc | Reporter: | Martin Sebor <msebor> |
Component: | middle-end | Assignee: | Martin Sebor <msebor> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | clyon |
Priority: | P3 | Keywords: | diagnostic, missed-optimization, patch |
Version: | 11.0 | ||
Target Milestone: | 12.0 | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2020-10-13 00:00:00 | |
Bug Depends on: | |||
Bug Blocks: | 88443 |
Description
Martin Sebor
2020-09-11 21:10:42 UTC
Whether or not this is diagnosed depends on the form of the IL and that in turn depends on the target. For example, when configured for aarch64-linux, GCC doesn't issue any warnings for the test case in comment #0. When configured for x86_64 it issues the following barrage of warnings (for g1 only). This is behind failures in the gcc.dg/Wstringop-overflow-47.c test reported here: https://gcc.gnu.org/pipermail/gcc-patches/2020-October/556049.html $ gcc -O2 -S pr97027.c pr97027.c: In function ‘g1’: pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 1 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 2 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 3 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 4 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 5 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 6 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 7 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 8 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 9 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 10 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 11 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 12 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 13 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 14 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 15 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 16 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 17 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 18 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 19 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 20 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 21 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 22 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 23 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 24 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 25 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 26 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 27 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 28 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 29 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 30 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 31 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 32 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 33 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 34 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 35 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 36 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 37 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 38 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 39 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 40 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 41 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 42 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 43 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 44 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 45 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 46 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 47 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 48 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 49 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 50 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 51 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 52 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 53 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 54 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 55 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 56 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 57 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 58 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 59 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 60 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 61 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 62 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 63 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ pr97027.c:36:12: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 36 | *(V64*)p = (V64){ i }; // storing 64 bytes at offset 1 into a one-byte array | ~~~~~~~~~^~~~~~~~~~~~ pr97027.c:33:8: note: at offset 64 to object ‘a’ with size 1 declared here 33 | char a[1]; | ^ Another test case. Of the buffer overflow in the four functions in it, only a subset is diagnosed. The subset depends on the form of the assignment in the IL which in turn changes from target to target. The output below is for aarch64 which is different for x86_64. $ cat xx.c && gcc -O2 -S -fdump-tree-optimized=/dev/stdout xx.c void f16 (char c) { typedef __attribute__ ((__vector_size__ (16))) char C16; extern char a16[16]; void *p = a16 + 1; *(C16*)p = (C16){ c }; } void f32 (char c) { typedef __attribute__ ((__vector_size__ (32))) char C32; extern char a32[32]; void *p = a32 + 1; *(C32*)p = (C32){ c }; } void f64 (char c) { typedef __attribute__ ((__vector_size__ (64))) char C64; extern char a64[64]; void *p = a64 + 1; *(C64*)p = (C64){ c }; } void f128 (char c) { typedef __attribute__ ((__vector_size__ (128))) char C128; extern char a128[128]; void *p = a128 + 1; *(C128*)p = (C128){ c }; } ;; Function f16 (f16, funcdef_no=0, decl_uid=3585, cgraph_uid=1, symbol_order=0) f16 (char c) { vector(16) char _1; <bb 2> [local count: 1073741824]: _1 = {c_2(D)}; MEM[(C16 *)&a16 + 1B] = _1; return; } ;; Function f32 (f32, funcdef_no=1, decl_uid=3593, cgraph_uid=2, symbol_order=1) f32 (char c) { vector(32) char _1; <bb 2> [local count: 1073741824]: _1 = {c_2(D)}; MEM[(C32 *)&a32 + 1B] = _1; return; } ;; Function f64 (f64, funcdef_no=2, decl_uid=3601, cgraph_uid=3, symbol_order=2) f64 (char c) { vector(64) char _1; <bb 2> [local count: 1073741824]: _1 = {c_2(D)}; MEM[(C64 *)&a64 + 1B] = _1; return; } xx.c: In function 'f128': xx.c:34:13: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 34 | *(C128*)p = (C128){ c }; | ~~~~~~~~~~^~~~~~~~~~~~~ xx.c:32:15: note: at offset 128 to object 'a128' with size 128 declared here 32 | extern char a128[128]; | ^~~~ ;; Function f128 (f128, funcdef_no=3, decl_uid=3609, cgraph_uid=4, symbol_order=3) f128 (char c) { <bb 2> [local count: 1073741824]: BIT_FIELD_REF <MEM[(C128 *)&a128 + 1B], 8, 0> = c_2(D); MEM <unsigned long> [(C128 *)&a128 + 2B] = 0; MEM <unsigned long> [(C128 *)&a128 + 10B] = 0; MEM <unsigned long> [(C128 *)&a128 + 18B] = 0; MEM <unsigned long> [(C128 *)&a128 + 26B] = 0; MEM <unsigned long> [(C128 *)&a128 + 34B] = 0; MEM <unsigned long> [(C128 *)&a128 + 42B] = 0; MEM <unsigned long> [(C128 *)&a128 + 50B] = 0; MEM <unsigned long> [(C128 *)&a128 + 58B] = 0; MEM <unsigned long> [(C128 *)&a128 + 66B] = 0; MEM <unsigned long> [(C128 *)&a128 + 74B] = 0; MEM <unsigned long> [(C128 *)&a128 + 82B] = 0; MEM <unsigned long> [(C128 *)&a128 + 90B] = 0; MEM <unsigned long> [(C128 *)&a128 + 98B] = 0; MEM <unsigned long> [(C128 *)&a128 + 106B] = 0; MEM <unsigned long> [(C128 *)&a128 + 114B] = 0; MEM <unsigned int> [(C128 *)&a128 + 122B] = 0; MEM <unsigned short> [(C128 *)&a128 + 126B] = 0; BIT_FIELD_REF <MEM[(C128 *)&a128 + 1B], 8, 1016> = 0; return; } The following change seems to take care of the problem: diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index ebb17cd852c..f04a1e4297d 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -4678,9 +4678,10 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset, if (gimple_assign_single_p (stmt)) { exp = gimple_assign_rhs1 (stmt); - if (TREE_CODE (exp) != MEM_REF) + if (TREE_CODE (exp) != CONSTRUCTOR + && TREE_CODE (exp) != MEM_REF) return false; - /* Handle MEM_REF below. */ + /* Handle CONSTRUCTOR and MEM_REF below. */ } else if (gimple_code (stmt) == GIMPLE_PHI) { @@ -4704,6 +4705,23 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset, } } + if (TREE_CODE (exp) == CONSTRUCTOR) + { + if (nbytes) + return false; + + tree type = TREE_TYPE (exp); + tree size = TYPE_SIZE_UNIT (type); + if (!size || !tree_fits_uhwi_p (size)) + return false; + + unsigned HOST_WIDE_INT byte_size = tree_to_uhwi (size); + if (byte_size < offset) + return false; + + nbytes = byte_size - offset; + } + if (TREE_CODE (exp) == MEM_REF) { if (nbytes) The master branch has been updated by Martin Sebor <msebor@gcc.gnu.org>: https://gcc.gnu.org/g:a110855667782dac7b674d3e328b253b3b3c919b commit r12-2132-ga110855667782dac7b674d3e328b253b3b3c919b Author: Martin Sebor <msebor@redhat.com> Date: Wed Jul 7 14:05:25 2021 -0600 Correct handling of variable offset minus constant in -Warray-bounds [PR100137] Resolves: PR tree-optimization/100137 - -Warray-bounds false positive on varying offset plus negative PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional PR tree-optimization/97027 - missing warning on buffer overflow storing a larger scalar into a smaller array gcc/ChangeLog: PR tree-optimization/100137 PR tree-optimization/99121 PR tree-optimization/97027 * builtins.c (access_ref::access_ref): Also set offmax. (access_ref::offset_in_range): Define new function. (access_ref::add_offset): Set offmax. (access_ref::inform_access): Handle access_none. (handle_mem_ref): Clear ostype. (compute_objsize_r): Handle ASSERT_EXPR. * builtins.h (struct access_ref): Add offmax member. * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use compute_objsize() and simplify. gcc/testsuite/ChangeLog: PR tree-optimization/100137 PR tree-optimization/99121 PR tree-optimization/97027 * c-c++-common/Warray-bounds-3.c: Remove xfail * c-c++-common/Warray-bounds-4.c: Add an expected warning. * c-c++-common/Warray-bounds-9.c: New test. * c-c++-common/Warray-bounds-10.c: New test. * g++.dg/asan/asan_test.C: Suppress expected warnings. * g++.dg/pr95768.C: Same. * g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages. * g++.dg/warn/Warray-bounds-11.C: Same. * g++.dg/warn/Warray-bounds-12.C: Same. * g++.dg/warn/Warray-bounds-13.C: Same. * g++.dg/warn/Warray-bounds-17.C: Same. * g++.dg/warn/Warray-bounds-20.C: Same. * gcc.dg/Warray-bounds-29.c: Same. * gcc.dg/Warray-bounds-30.c: Add xfail. * gcc.dg/Warray-bounds-31.c: Adjust text of expected messages. * gcc.dg/Warray-bounds-32.c: Same. * gcc.dg/Warray-bounds-52.c: Same. * gcc.dg/Warray-bounds-53.c: Same. * gcc.dg/Warray-bounds-58.c: Remove xfail. * gcc.dg/Warray-bounds-63.c: Adjust text of expected messages. * gcc.dg/Warray-bounds-66.c: Same. * gcc.dg/Warray-bounds-69.c: Same. * gcc.dg/Wstringop-overflow-34.c: Same. * gcc.dg/Wstringop-overflow-47.c: Same. * gcc.dg/Wstringop-overflow-61.c: Same. * gcc.dg/Warray-bounds-77.c: New test. * gcc.dg/Warray-bounds-78.c: New test. * gcc.dg/Warray-bounds-79.c: New test. Fixed in GCC 12.0. Still not completely fixed. gcc.dg/Wstringop-overflow-47.c still fails on aarch64 due to the different IL. The test below (extracted from Wstringop-overflow-47.c) is diagnosed as expected with an x86_64 native GCC but now with an aarch64 cross. $ cat t.c && /build/aarch64-linux/gcc-master/gcc/xgcc -B /build/aarch64-linux/gcc-master/gcc -O2 -S -fdump-tree-optimized=/dev/stdout t.c typedef __INT16_TYPE__ int16_t; typedef __attribute__ ((__vector_size__ (32))) char C32; void warn_c32 (char c) { extern char warn_a32[32]; // { dg-message "at offset 32 into destination object 'warn_a32' of size 32" "pr97027" } void *p = warn_a32 + 1; *(C32*)p = (C32){ c }; // { dg-warning "writing 1 byte into a region of size 0" "pr97027" } } ;; Function warn_c32 (warn_c32, funcdef_no=0, decl_uid=3908, cgraph_uid=1, symbol_order=0) void warn_c32 (char c) { vector(32) char _1; <bb 2> [local count: 1073741824]: _1 = {c_2(D)}; MEM[(C32 *)&warn_a32 + 1B] = _1; return; } Something like the patch in comment 3 to handle the overflow in tree-ssa-strlen.c is still needed. Otherwise GCC does issue a -Warray-bounds but that's enabled only with -Wall (the test expects buffer overflow to be detected without -Wall). Note that we still have failures on arm similar to what you mention on aarch64. FAIL: gcc.dg/Wstringop-overflow-47.c pr97027 (test for warnings, line 34) FAIL: gcc.dg/Wstringop-overflow-47.c pr97027 (test for warnings, line 37) FAIL: gcc.dg/Wstringop-overflow-47.c pr97027 (test for warnings, line 42) The master branch has been updated by Martin Sebor <msebor@gcc.gnu.org>: https://gcc.gnu.org/g:f0500db3692276f60e0562c17c87a0cb03e34398 commit r12-2338-gf0500db3692276f60e0562c17c87a0cb03e34398 Author: Martin Sebor <msebor@redhat.com> Date: Thu Jul 15 13:15:03 2021 -0600 Detect buffer overflow by aggregate and vector stores [PR97027]. Resolves: PR middle-end/97027 - missing warning on buffer overflow storing a larger scalar into a smaller array gcc/ChangeLog: PR middle-end/97027 * tree-ssa-strlen.c (handle_assign): New function. (maybe_warn_overflow): Add argument. (nonzero_bytes_for_type): New function. (count_nonzero_bytes): Handle more tree types. Call nonzero_bytes_for_tye. (count_nonzero_bytes): Handle types. (handle_store): Handle stores from function calls. (strlen_check_and_optimize_call): Move code to handle_assign. Call it for assignments from function calls. gcc/testsuite/ChangeLog: PR middle-end/97027 * gcc.dg/Wstringop-overflow-15.c: Remove an xfail. * gcc.dg/Wstringop-overflow-47.c: Adjust xfails. * gcc.dg/torture/pr69170.c: Avoid valid warnings. * gcc.dg/torture/pr70025.c: Prune out a false positive. * gcc.dg/vect/pr97769.c: Initialize a loop control variable. * gcc.target/i386/pr92658-avx512bw-trunc.c: Increase buffer size to avoid overflow. * gcc.target/i386/pr92658-avx512f.c: Same. * gcc.dg/Wstringop-overflow-68.c: New test. * gcc.dg/Wstringop-overflow-69.c: New test. * gcc.dg/Wstringop-overflow-70.c: New test. * gcc.dg/Wstringop-overflow-71.c: New test. * gcc.dg/strlenopt-95.c: New test. With r12-2338 Wstringop-overflow-47.c passes on aarch64, arm, as well as x86_64, so this can now be fully resolved. |