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

            Bug ID: 81592
           Summary: spurious -Wformat-overflow warning with
                    -fsanitize=signed-integer-overflow
           Product: gcc
           Version: 7.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arnd at linaro dot org
  Target Milestone: ---

While testing the linux kernel with -fsanitize=signed-integer-overflow, I ran
into a bogus warning for sprintf format overflow for
security/keys/proc.c:proc_keys_show.

I have reduced the source file to this code snippet:

/* aarch64-linux-gcc-7.1.1 -O2 -c test.c -Wall -fno-strict-overflow 
-Wstrict-overflow=2 -fsanitize=signed-integer-overflow */
#include <stdio.h>

int proc_keys_show(long expiry, long now)
{
        unsigned long timo;
        char xbuf[4];

        if (now < expiry) {
                timo = expiry - now;
                if (timo < 60)
                        sprintf(xbuf, "%lus", timo);
        }

        return 0;
}

When building with either -fwrapv or -fsanitize=signed-integer-overflow, I get
this warning:

test.c: In function '_proc_keys_show':
test.c:12:19: warning: '%lu' directive writing between 1 and 20 bytes into a
region of size 4 [-Wformat-overflow=]
    sprintf(xbuf, "%lus", timo);
                   ^~~
test.c:12:18: note: directive argument in the range [1, 18446744073709551615]
    sprintf(xbuf, "%lus", timo);
                  ^~~~~~
test.c:12:4: note: 'sprintf' output between 3 and 22 bytes into a destination
of size 4
    sprintf(xbuf, "%lus", timo);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~


Building with just "-O2 -Wstrict-overflow=2" produces a different warning that
is also surprising:

test.c: In function '_proc_keys_show':
test.c:11:6: warning: assuming signed overflow does not occur when simplifying
conditional [-Wstrict-overflow]
   if (timo < 60)


As Jim Wilson mentioned on IRC, the first comparison here clearly determines
that no signed overflow can happen, and apparently that leads to the second
comparison being done using signed arithmetic, but then the compiler decides to
use a signed comparison and incorrectly assumes that it might have overflown.

This seems to be related to pr 79257 and pr 78969, but both of them are
sufficiently different that I decided to open a separate report here.

Reply via email to