https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108091
Bug ID: 108091 Summary: '-Wformat-overflow' determines incorrect size when printing strings from an array of structs Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: cjamcl at gmail dot com Target Milestone: --- Given an array of structs for which a member is a `char[]`, `-Wformat-overflow` will be far too conservative in its determination of how big the printed value can be. Repro: https://gcc.godbolt.org/z/K69baxW55 ```c // gcc -Os -Wformat-overflow -c test.c struct my_struct { char name[64]; int id; }; struct my_struct list[]= { { "A", 0}, { "B", 0}, { "C", 0}, { "", 0}, }; int main() { char str[100]; for (int i = 0; i < 4; i++) { __builtin_sprintf(str, "%s", list[i].name); } return 0; } ``` Output: ``` <source>: In function 'int main()': <source>:19:33: warning: '%s' directive writing up to 271 bytes into a region of size 100 [-Wformat-overflow=] 19 | __builtin_sprintf(str, "%s", list[i].name); | ^~ <source>:19:26: note: '__builtin_sprintf' output between 1 and 272 bytes into a destination of size 100 19 | __builtin_sprintf(str, "%s", list[i].name); | ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~ Compiler returned: 0 ``` ----- My assumption is that it cannot be determined that some value doesn't get a non-null terminated string written to it at runtime, so the check is very conservative and gives a length equal to the full size of the array. In the above example, I'd expect gcc to know that the values are never re-assigned, so it should use the length of whatever the biggest string in the array is. I attempted to help the check by adding `const` qualifiers but that didn't help.