This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug middle-end/78605] New: bogus -Wformat-length=1 with %f


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

            Bug ID: 78605
           Summary: bogus -Wformat-length=1 with %f
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

This issue was raised on the gcc list:
  https://gcc.gnu.org/ml/gcc/2016-11/msg00102.html

In my response I didn't fully understand the problem that was being pointed
out.  Here's a smaller test case that should hopefully make it clearer.  The
issue is that while there is no warning for the sprintf call in f one is
emitted for the call in g.  In both instances the arguments of the call are
unknown and may take on values that will fit into the provided buffer as well
as values that will not.  The -Wformat-length=1 setting is supposed to be
conservative in diagnosing potential overflows by assuming unknown integers
have the value 1.  The same logic should apply to floating point arguments, so
the warning for g is a false positive.

$ cat c.c && gcc -S -O2 -Wall -Wextra c.c
char d[10];

int f (int i)
{
  return __builtin_sprintf (d, "%i %i", i, i);
}

int g (float f)
{
  return __builtin_sprintf (d, "%.2f %.2f", f, f);
}
c.c: In function ‘g’:
c.c:10:38: warning: ‘%.2f’ directive writing between 4 and 317 bytes into a
region of size 0 [-Wformat-length=]
   return __builtin_sprintf (d, "%.2f %.2f", f, f);
                                      ^~~~
c.c:10:10: note: format output between 10 and 636 bytes into a destination of
size 10
   return __builtin_sprintf (d, "%.2f %.2f", f, f);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Compiling with -Wformat-length=2 on the other hand emits a warning for the
sprintf call in f because the unknown argument is assumed to take on the value
that results in the largest number of bytes (in  this case -DBL_MAX). 
Similarly, the sprintf call in g is diagnosed (as expected).  What is missing
is a note indicating the range of values the checker considers in the floating
case.

As an independent issue, since the type of the arguments to the %f directive is
float (not double), the checker should use -FLT_MAX rather than -DBL_MAX to
determine the output.

As another, separate, issue, the underlining seems off in the first note in the
integer case.

c.c: In function ‘f’:
c.c:5:33: warning: ‘%i’ directive writing between 1 and 11 bytes into a region
of size 10 [-Wformat-length=]
   return __builtin_sprintf (d, "%i %i", i, i);
                                 ^~
c.c:5:32: note: using the range [‘1’, ‘-2147483648’] for directive argument
   return __builtin_sprintf (d, "%i %i", i, i);
                                ^~~~~~~
c.c:5:10: note: format output between 4 and 24 bytes into a destination of size
10
   return __builtin_sprintf (d, "%i %i", i, i);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
c.c: In function ‘g’:
c.c:10:33: warning: ‘%.2f’ directive writing between 4 and 317 bytes into a
region of size 10 [-Wformat-length=]
   return __builtin_sprintf (d, "%.2f %.2f", f, f);
                                 ^~~~
c.c:10:10: note: format output between 10 and 636 bytes into a destination of
size 10
   return __builtin_sprintf (d, "%.2f %.2f", f, f);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]