there is no obvious way to silence the sprintf %s warning. (this currently breaks the gdb build) $ cat a.c int sprintf (char*, const char*, ...); struct { char buf[12]; } s; void f(void) { char foo[7]; if (__builtin_strlen(s.buf) > 3) // this check does not help return; sprintf(foo, "zz%s", s.buf); } $ gcc -Wall -c a.c a.c: In function 'f': a.c:10:19: warning: '%s' directive writing between 0 and 11 bytes into a region of size 5 [-Wformat-length=] sprintf(foo, "zz%s", s.buf); ^~ ~ a.c:10:3: note: format output between 3 and 14 bytes into a destination of size 7 sprintf(foo, "zz%s", s.buf); ^~~~~~~~~~~~~~~~~~~~~~~~~~~
Unfortunately, even though it seems like the if statement with the strlen call should help, the length range information isn't available to the warning pass. The warning can, however, be avoided by constraining the length of the string argument output by specifying the precision in the directive like so: sprintf(foo, "zz%.4s", s.buf); Please let me know if this isn't sufficient to resolve the problem report.
(In reply to Martin Sebor from comment #1) > sprintf(foo, "zz%.4s", s.buf); > > Please let me know if this isn't sufficient to resolve the problem report. in my case truncation is fatal error so using precision is not useful (other than suppressing the warning) and has a runtime cost (extra arg passing for %.*s).
(In reply to nsz from comment #2) > in my case truncation is fatal error so using precision is not useful (other > than suppressing the warning) and has a runtime cost (extra arg passing for > %.*s). nevermind, i'll just use snprintf.
Note that with snprintf GCC issues warning: ‘%s’ directive output may be truncated writing between 1 and 11 bytes into a region of size 5 This is also by design though I'm on the fence about warning at the same level or under the same option as for sprintf. FWIW, I wouldn't expect the parsing of the precision within the format string to have a noticeable performance impact on the overall cost of the call to the function. If you prefer to avoid it, you can specify via an argument to the '*': sprintf(foo, "zz%.*s", 4, s.buf); I'm changing the resolution of this bug to invalid since we haven't actually fixed anything, but if none of the solutions above is sufficient please feel free to reopen the bug and let us know what would be (keeping in mind that the ideal solution of tracking the actual string length or its range or determining it from the strlen call may not be feasible in the near term).
(In reply to Martin Sebor from comment #4) > Note that with snprintf GCC issues > > warning: ‘%s’ directive output may be truncated writing between 1 and 11 > bytes into a region of size 5 > > This is also by design though I'm on the fence about warning at the same > level or under the same option as for sprintf. > i opened another bug about snprintf https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77708 i think warning for snprintf is almost surely a false positive, that is hard to suppress (and the suppression code is not idiomatic).