Reputation: 132320
Suppose I have a function taking an int *p
which I know for a fact only points to values between 0 and 99. However, the compiler doesn't know that, so if I write:
char buffer[3];
snprintf(buffer, "%02d", *p);
I get a warning (at least, on GCC 8.x) - it's something like:
warning: ‘%02d’ directive output may be truncated writing between 2 and 11 bytes into a region of size 2 [-Wformat-truncation=]
snprintf(buffer, "%02d", *p);
How should I circumvent this warning?
Upvotes: 2
Views: 1132
Reputation: 132320
I can think of three ways of avoiding the warning:
Local suppression using a GCC pragma:
#if __GNUC__ >= 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation"
#endif
snprintf(buffer, "%02d", *p);
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
Uselessly clamp the printed value to make the compiler aware of the range:
char buffer[3];
int clamped_value = min(max(*p,0),99)` and print that instead of `*p`.
snprintf(buffer, "%02d", clamped_value);
Artificially inflate the buffer size by an extra 9 bytes;
char buffer[3+9];
snprintf(buffer, "%02d", p);
But I don't like any of these much. The first way is less safe (and more verbose); The second one wastes clock cycles and the third one wastes stack space.
Upvotes: 2
Reputation: 56
This code compiles and runs fine for me on GCC 8.3.1:
#include <stdio.h>
#define BUF_SZ 3
int main(void)
{
int foo = 99;
int *p = (int *)&foo;
char buffer[BUF_SZ];
snprintf(buffer, BUF_SZ, "%02d", *p);
fprintf(stdout, "%s\n", buffer);
return 0;
}
me@localhost:/tmp$ gcc -v 2>&1 | grep "gcc version"
gcc version 8.3.1 20190223 (Red Hat 8.3.1-2) (GCC)
me@localhost:/tmp$ gcc -Wall test.c && ./a.out
99
Perhaps this version of GCC doesn't have the issue but I did notice above that you have
snprintf(buffer, "%02d", *p);
- which shouldn't compile at all since you're missing the size parameter to snprintf.
Also, it's worth noting that with the following diff, GCC 8.3.1 does throw the error as expected:
me@localhost:/tmp$ diff test.c test_format-truncation-warning.c
11c11
< snprintf(buffer, BUF_SZ, "%02d", *p);
---
> snprintf(buffer, BUF_SZ, "%03d", *p);
For others who stumble onto this page looking for a more general "workaround" for -Wformat-truncation warnings. Here's one which uses memcpy() though I doubt the authors of -Wformat-truncation intended for it to be used as an alternative to strncpy().
#if USE_STRNCPY
/* Note that using size of 'NAME_MAX' is just to prevent recent versions
* of GCC from throwing '-Wformat-truncation' errors. Otherwise, a char
* buffer of len UUID_STR_LEN would be fine.
*/
char tmp_fname[NAME_MAX + 1] = {0};
strncpy(tmp_fname, input_file_name, NAME_MAX);
#else
char tmp_fname[UUID_STR_LEN] = {0};
memcpy((void *)tmp_fname, (void *)input_file_name,
MIN(UUID_STR_LEN - 1, strnlen(input_file_name, UUID_STR_LEN - 1));
#endif
Upvotes: 0