Bug 113752 - [14/15 Regression] warning: ‘%s’ directive writing up to 10218 bytes into a region of size between 0 and 10240 [-Wformat-overflow=] since r14-261-g0ef3756adf078c
Summary: [14/15 Regression] warning: ‘%s’ directive writing up to 10218 bytes into a r...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 14.0
: P2 normal
Target Milestone: 14.2
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wformat-overflow
  Show dependency treegraph
 
Reported: 2024-02-04 04:34 UTC by H.J. Lu
Modified: 2024-05-07 07:44 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2024-02-04 00:00:00


Attachments
A testcase (20.80 KB, application/octet-stream)
2024-02-04 04:34 UTC, H.J. Lu
Details

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2024-02-04 04:34:07 UTC
Created attachment 57315 [details]
A testcase

[hjl@gnu-tgl-2 tmp]$  /usr/gcc-14.0.1-x32-apx/bin/gcc -O3 -S x.i -Wall 
In file included from tests-mbwc/tst_wctype.c:8:
tests-mbwc/tsp_common.c: In function ‘result.constprop.isra’:
tests-mbwc/tsp_common.c:55:24: warning: ‘%s’ directive writing up to 10218 bytes into a region of size between 0 and 10240 [-Wformat-overflow=]
tests-mbwc/tsp_common.c:55:3: note: ‘sprintf’ output between 18 and 20484 bytes into a destination of size 10256
[hjl@gnu-tgl-2 tmp]$ 

GCC 13 is OK.
Comment 1 H.J. Lu 2024-02-04 05:58:02 UTC
It is caused by r14-261.
Comment 2 H.J. Lu 2024-02-04 06:15:35 UTC
[hjl@gnu-skx-1 gcc]$ cat /tmp/foo.i
char a[10256];
char b;
char *c, *g;
int d, e, f;
int sprintf(char *, char *, ...);
unsigned long strlen(char *);
int h(char *j) {
  if (strlen(j) + strlen(c) + strlen(g) + 32 > 10256)
    return 0;
  sprintf(a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
  return 1;
}
void i() { h("wctype"); }
[hjl@gnu-skx-1 gcc]$ ./xgcc -B./ -O3 -Wall -S /tmp/foo.i
/tmp/foo.i: In function ?i?:
/tmp/foo.i:10:33: warning: ?%s? directive writing up to 10218 bytes into a region of size between 0 and 10240 [-Wformat-overflow=]
   10 |   sprintf(a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
      |                                 ^~
In function ?h?,
    inlined from ?i? at /tmp/foo.i:13:12:
/tmp/foo.i:10:3: note: ?sprintf? output between 18 and 20484 bytes into a destination of size 10256
   10 |   sprintf(a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[hjl@gnu-skx-1 gcc]$
Comment 3 Aldy Hernandez 2024-02-12 09:46:44 UTC
Can't reproduce on x86-64 on recent trunk:

abulafia:~/bld/t/gcc []$ ./xgcc -B./ -c -O3 -Wall a.c
abulafia:~/bld/t/gcc []$ cat a.c
char a[10256];
char b;
char *c, *g;
int d, e, f;
int sprintf(char *, char *, ...);
unsigned long strlen(char *);
int h(char *j) {
  if (strlen(j) + strlen(c) + strlen(g) + 32 > 10256)
    return 0;
  sprintf(a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
  return 1;
}
Comment 4 Jakub Jelinek 2024-02-12 10:09:36 UTC
Strange, it certainly does reproduce for me:
char a[10256], b, *c, *g;
int d, e, f;

int
foo (char *j)
{
  if (__builtin_strlen (j) + __builtin_strlen (c) + __builtin_strlen (g) + 32 > 10256)
    return 0;
  __builtin_sprintf (a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
  return 1;
}

void
bar (void)
{
  foo ("wctype");
}
/volume/tor/opt/notnfs/gcc-bisect/obj/gcc/cc1.r14-8919 -quiet -O3 -Wall pr113752.c
pr113752.c: In function ‘bar’:
pr113752.c:9:44: warning: ‘%s’ directive writing up to 10218 bytes into a region of size between 0 and 10240 [-Wformat-overflow=]
    9 |   __builtin_sprintf (a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
      |                                            ^~
In function ‘foo’,
    inlined from ‘bar’ at pr113752.c:16:3:
pr113752.c:9:3: note: ‘__builtin_sprintf’ output between 18 and 20484 bytes into a destination of size 10256
    9 |   __builtin_sprintf (a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/volume/tor/opt/notnfs/gcc-bisect/obj/gcc/cc1.r14-260 -quiet -O3 -Wall pr113752.c
/volume/tor/opt/notnfs/gcc-bisect/obj/gcc/cc1.r14-261 -quiet -O3 -Wall pr113752.c
pr113752.c: In function ‘bar’:
pr113752.c:9:44: warning: ‘%s’ directive writing up to 10218 bytes into a region of size between 0 and 10240 [-Wformat-overflow=]
    9 |   __builtin_sprintf (a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
      |                                            ^~
In function ‘foo’,
    inlined from ‘bar’ at pr113752.c:16:3:
pr113752.c:9:3: note: ‘__builtin_sprintf’ output between 18 and 20484 bytes into a destination of size 10256
    9 |   __builtin_sprintf (a, "%s:%s:%d:%d:%d:%c:%s\n", j, c, d, e, f, b, g);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 5 Jakub Jelinek 2024-02-12 10:23:23 UTC
That said, the math at least in the reduced testcase is weird.
%d output is at most 11 bytes - strlen ("-2147483648"), + 9 other chars, so that
is 42, not 32.  But even using + 42 in there instead of 32 doesn't fix it.
It wouldn't surprise me if the misdesigned warning just sees that each of the strlens clearly has a range [0, 10256-42], after all, when expressed as a range there isn't much more to derive about it, and then uses that [0, 10214] range for each of the %s
specifiers.  Though, that is not what the warning says.  Ah, maybe it is because j is known short after inlining or some IPA opts.
Also, because the strlen + strlen + strlen + cst > cst2 condition uses unsigned type, wrap around is theoretically possible, e.g. one could have some PTRDIFF_MAX - epsilon sized string and call it with c = g = j that string.
Comment 6 H.J. Lu 2024-02-12 13:52:46 UTC
I can reproduce it with r14-8930-g1e94648ab7b370
Comment 7 Jakub Jelinek 2024-02-13 11:36:24 UTC
Anyway, I think the testcase is very similar to
char a[256], *c, *g;

int
foo (void)
{
  if (__builtin_strlen (c) + __builtin_strlen (g) + 5 > 256)
    return 0;
  __builtin_sprintf (a, "abcd%s%s", c, g);
  return 1;
}
which has started diagnosing this with r12-5014-g6b8b959675a3e14cfdd2145bd62e4260eb193765 at -O2 -Wall -W
Comment 8 Richard Biener 2024-05-07 07:44:49 UTC
GCC 14.1 is being released, retargeting bugs to GCC 14.2.