6

There's this code I'm compling, which has the line:

snprintf(target, 11, "%02ld-%02ld-19%02ld", day, month, year);

... which is executed after it has been verified that all 3 values are valid; and specifically, that year is between 0 and 99.

However, recent versions of GCC, when run with -Wextra, complain:

warning: ‘%02ld’ directive output may be truncated writing between 2 and 20 bytes
into a region of size 3 [-Wformat-truncation=]

I would rather not entirely disable this warning; nor even disable it locally. Instead, I am wondering if I could somehow "convince" GCC of the value range for the three arguments, preventing the warning.

Yes, this is rather ugly code that reinvents the wheel, and locale-specific routines for date formatting should be used, no need to lecture me; not my code.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • With your example I can only see this warning when I change the 11 to a smaller value. Can you post a small piece of code that can reproduce the warning? – hko Dec 09 '19 at 17:58
  • [This question](https://stackoverflow.com/questions/51534284/how-to-circumvent-format-truncation-warning-in-gcc) seems to address a related problem. – Gerd Dec 09 '19 at 18:16
  • @Gerd: Thanks for the link; it's related but not a dupe, since in that case truncation is possible, and in my case - it isn't. – einpoklum Dec 09 '19 at 19:00
  • Which version of GCC? https://tio.run/##PY7LasMwEEX3@orBIWCDFKx2VVzyC1lmkXQxSH4I5FGRJyEh5NerKLbp5t7LPM6MUb0xaePI@Itt4Xti68Ju2AtxDc5CFwKUPlAPFu8S5jQG4mHN9xZjBQ9hBozAGPuWT1r/NGmi3@iIu3IpStBaQrGtP7xVi@qv2Qu5oFfqDGzSulxspzPliQVSNeIpRG7AiI6gzIffD5a6rmv5L1UDz/RnOo/9lNThM6lje@OI2dH7rF2II7LieCGD7AK9AA – jxh Dec 09 '19 at 19:56
  • Seems like the same as this one [How to stop GCC complaining about “directive output may be truncated” in snprintf() call?](https://stackoverflow.com/questions/57780368/how-to-stop-gcc-complaining-about-directive-output-may-be-truncated-in-snprint) Even the same answer – hko Dec 09 '19 at 20:01
  • @hko True. I saw this post similar yet slightly different and wanted to offer more alternatives. – chux - Reinstate Monica Dec 09 '19 at 20:28

1 Answers1

4

if I could somehow "convince" GCC of the value range for the three arguments, preventing the warning.

Let the compiler know that all values used are of 1-2 digits with reduced range type, &, %, / or etc.

In this case, recommend unsigned math and %.
(Note: recall some_int%100 results are in the range -99 to 99, up to 3 characters, hence the reason for unsigned math.)

char target[11];
//                               dd   -dd   -19dd   \0   0-99         0-99        0-99   
snprintf(target, sizeof target, "%02lu-%02lu-19%02lu", day%100lu, month%100lu, year%100lu);

A smart enough compiler will see % and analyse accordingly.


Since month and day are in the range 1-12 and 1-31, could use month & 15, day & 31, but that micro optimization lacks clarity.


If day%100lu brings up an undesirable warning about mixed sign-ness, then

snprintf(target, sizeof target, "%02u-%02u-19%02u",
    (unsigned)day%100u, (unsigned)month%100u, (unsigned)year%100u);

or simply use a wider target ;-)

Perhaps the below if a generous buffer is not prohibitive.

#define CHAR_PER_LONG_N (CHAR_BIT*sizeof(long)/3+3)
#define DATE_FMT %02ld-%02ld-19%02ld"
#define BUF_N (sizeof DATE_FMT + 3*CHAR_PER_LONG_N)
char target[BUF_N];

snprintf(target, sizeof target, DATE_FMT, day, month, year);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256