https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103736

            Bug ID: 103736
           Summary: snprintf bogus format-truncation, disregarding modulo
                    on argument
           Product: gcc
           Version: 11.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: patrickdepinguin at gmail dot com
  Target Milestone: ---

gcc 11.2.0 and gcc 9.4.0 give a bogus format-truncation warning on following
test case compiled with -Wall and -O2:

#include <stdint.h>
#include <stdio.h>

void func(void) {

    extern int8_t timezoneval;
    char timezone[1+2+1];

    if(timezoneval < 0)
    {
         snprintf(timezone, sizeof(timezone),"-%02d",-(timezoneval % 100));
    }
    else
    {
         snprintf(timezone, sizeof(timezone),"+%02d", timezoneval % 100);
    }
}

Warning:

/tmp/test.cpp: In function 'void func()':
/tmp/test.cpp:15:52: warning: 'snprintf' output may be truncated before the
last format character [-Wformat-truncation=]
   15 |          snprintf(timezone, sizeof(timezone),"+%02d", timezoneval %
100);
      |                                                    ^
/tmp/test.cpp:15:18: note: 'snprintf' output between 4 and 5 bytes into a
destination of size 4
   15 |          snprintf(timezone, sizeof(timezone),"+%02d", timezoneval %
100);
      |         
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Since timezoneval is used modulo 100, it will not take up more than two digits
(note that if timezoneval is negative, its value is negated first, so the
string representation will be positive). Together with the literal sign
character, and the null-termination, max. total size is 4 bytes. Yet, gcc
considers that 5 bytes may be needed.

When the parentheses in the first snprintf are omitted, causing the modulo
operator to operate on the negated timezoneval, the warning disappears. Funnily
enough, the warning is about the _second_, unmodified, snprintf:


#include <stdint.h>
#include <stdio.h>

void func(void) {

    extern int8_t timezoneval;
    char timezone[1+2+1];

    if(timezoneval < 0)
    {
         snprintf(timezone, sizeof(timezone),"-%02d",-timezoneval % 100);
    }
    else
    {
         snprintf(timezone, sizeof(timezone),"+%02d", timezoneval % 100);
    }
}


I found some possibly related older bugs, but was unsure if it's the same and
known to still apply on gcc 11. Feel free to mark this one as duplicated to the
relevant one.

Bug #78969 - bogus snprintf truncation warning due to missing range info
Bug #77721 - -Wformat-truncation not uses arg range for converted vars 
Bug #94021 - -Wformat-truncation false positive due to excessive integer range
  • [Bug other/103736] New: snp... patrickdepinguin at gmail dot com via Gcc-bugs

Reply via email to