Bug 89977 - missing -Wstringop-overflow with an out-of-bounds int128_t range
Summary: missing -Wstringop-overflow with an out-of-bounds int128_t range
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wstringop-overflow
  Show dependency treegraph
 
Reported: 2019-04-04 19:47 UTC by Martin Sebor
Modified: 2021-08-10 23:09 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2019-04-04 19:47:24 UTC
Additional testing of the patch for pr89957 exposed the following:

GCC diagnoses the buffer overflow in f() below but fails to diagnose the same buffer overflow in g().  The get_range_info() function returns VR_VARYING for the int128_t variable in g().

$ cat z.c && gcc -S -O2 -Wall -Wextra -fdump-tree-optimized=/dev/stdout z.c
char a[3];

__attribute__ ((noipa))
void f (int n)
{
  if (n < 7)
    n = 7;
  __builtin_memset (a, 0, n);
}

__attribute__ ((noipa))
void g (__int128_t n)
{
  if (n < 7)
    n = 7;
  __builtin_memset (a, 0, n);
}
z.c: In function ‘f’:
z.c:8:3: warning: ‘__builtin_memset’ forming offset [4, 7] is out of the bounds [0, 3] of object ‘a’ with type ‘char[3]’ [-Warray-bounds]
    8 |   __builtin_memset (a, 0, n);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~
z.c:1:6: note: ‘a’ declared here
    1 | char a[3];
      |      ^

;; Function f (f, funcdef_no=0, decl_uid=1907, cgraph_uid=1, symbol_order=1)

__attribute__((noipa, noinline, noclone, no_icf))
f (int n)
{
  long unsigned int _1;

  <bb 2> [local count: 1073741824]:
  n_3 = MAX_EXPR <n_2(D), 7>;
  _1 = (long unsigned int) n_3;
  __builtin_memset (&a, 0, _1); [tail call]
  return;

}



;; Function g (g, funcdef_no=1, decl_uid=1910, cgraph_uid=2, symbol_order=2)

__attribute__((noipa, noinline, noclone, no_icf))
g (__int128 n)
{
  long unsigned int _1;

  <bb 2> [local count: 1073741824]:
  n_3 = MAX_EXPR <n_2(D), 7>;
  _1 = (long unsigned int) n_3;
  __builtin_memset (&a, 0, _1); [tail call]
  return;

}
Comment 1 JunMa 2019-04-08 07:34:33 UTC
in function f, the conversion of stmt  _1 = (long unsigned int) n_3 is extending, while in function g,  the conversion of stmt  _1 = (long unsigned int) n_3 is truncating. 
For integer type truncation, gcc compute the range of target only if the range size of source is less than what the precision of the target type can represent.

I think this can be relaxed when the target type of truncation is unsigned.
Comment 2 JunMa 2019-04-08 08:04:52 UTC
After a bit more thinking, the behavior of gcc trunk is right. the range of n_3 in truncation from int128 to long unsigned int equal to the range of long unsigned int. for example: if n_3 = 0x100000000, then _1 is 0 which is less than 7.

so this is not a bug.
Comment 3 JunMa 2019-04-08 08:08:12 UTC
(In reply to JunMa from comment #2)
> After a bit more thinking, the behavior of gcc trunk is right. the range of
> n_3 in truncation from int128 to long unsigned int equal to the range of
> long unsigned int. for example: if n_3 = 0x100000000, then _1 is 0 which is
> less than 7.
> 
> so this is not a bug.

sorry, when n_3 = 0x1000 00000000 00000000, _1 is 0.
Comment 4 Martin Sebor 2019-04-08 17:27:56 UTC
You're right that the conversion from int128_t to unsigned long can result in truncation, so the range of the result is that of unsigned long.  Yet I suspect that relying on it is more likely unintentional and a bug.  The question in my mind is whether narrowing int128_t conversions should be diagnosed just in these contexts (i.e., -Wstringop-overflow) or in others as well.
Comment 5 JunMa 2019-04-09 02:40:31 UTC
(In reply to Martin Sebor from comment #4)
> You're right that the conversion from int128_t to unsigned long can result
> in truncation, so the range of the result is that of unsigned long.  Yet I
> suspect that relying on it is more likely unintentional and a bug.  The
> question in my mind is whether narrowing int128_t conversions should be
> diagnosed just in these contexts (i.e., -Wstringop-overflow) or in others as
> well.

We have no idea whether these truncations is intentional or not in gcc side, maybe we need a new option such as Wstringop-truncation to do this.