Bug 79016 - missing -Wstringop-overflow= overflowing allocated buffers
Summary: missing -Wstringop-overflow= overflowing allocated buffers
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: 10.0
Assignee: Martin Sebor
URL:
Keywords: diagnostic, patch
Depends on:
Blocks: Wstringop-overflow
  Show dependency treegraph
 
Reported: 2017-01-06 16:15 UTC by Martin Sebor
Modified: 2020-04-22 21:03 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 10.0
Known to fail: 7.3.0, 8.3.0, 9.2.0
Last reconfirmed: 2017-08-28 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2017-01-06 16:15:31 UTC
The -Wstringop-overflow warning correctly detects the buffer overflow in the fauto() and funnamed() functions below but misses all the other instances of it in the rest of the functions.

$ cat b.c && gcc -O2 -S -Wall -Wextra -Wpedantic b.c
void f (void*);

void fauto (void)
{
  char d[3];

  f (__builtin_memset (d, 0, 5));
}

void funnamed (void)
{
  f (__builtin_memset ((char[3]){ 0 }, 1, 5));
}

void falloca (void)
{
  char *d = __builtin_alloca (3);

  f (__builtin_memset (d, 0, 5));
}

void fmalloc (void)
{
  char *d = __builtin_malloc (3);

  f (__builtin_memset (d, 0, 5));
}

void fvla (unsigned n)
{
  if (n > 3)
    n = 3;

  char d [n];

  f (__builtin_memset (d, 0, 5));
}

b.c: In function ‘fauto’:
b.c:7:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 overflows the destination [-Wstringop-overflow=]
   f (__builtin_memset (d, 0, 5));
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b.c: In function ‘funnamed’:
b.c:12:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 overflows the destination [-Wstringop-overflow=]
   f (__builtin_memset ((char[3]){ 0 }, 1, 5));
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 1 Eric Gallager 2017-08-28 19:55:38 UTC
Confirmed.
Comment 2 Martin Sebor 2018-02-06 22:15:54 UTC
This is also affects overflowing buffers allocated by a user-defined function declared with attribute alloc_size.

$ cat t.c && gcc -D_FORTIFY_SOURCE=2 -O2 -S -Wall -fdump-tree-optimized=/dev/stdout t.c
#include <string.h>

int* __attribute__ ((alloc_size (1)))
f (int);

void* g (const void *s)
{
  void *p = f (8);
  __builtin_memcpy (p, s, 9);   // missing -Wstringop-overflow
  return p;
}

void* h (const void *s)
{
  void *p = f (8);
  memcpy (p, s, 9);   // -Wstringop-overflow with _FORTIFY_SOURCE
  return p;
}

;; Function g (g, funcdef_no=14, decl_uid=2244, cgraph_uid=14, symbol_order=14)

g (const void * s)
{
  void * p;

  <bb 2> [local count: 1073741825]:
  p_3 = f (8);
  __builtin_memcpy (p_3, s_4(D), 9);
  return p_3;

}



;; Function h (h, funcdef_no=15, decl_uid=2248, cgraph_uid=15, symbol_order=15)

h (const void * s)
{
  void * p;

  <bb 2> [local count: 1073741825]:
  p_3 = f (8);
  __builtin___memcpy_chk (p_3, s_4(D), 9, 8);
  return p_3;

}


In file included from /usr/include/string.h:635,
                 from t.c:1:
In function ‘memcpy’,
    inlined from ‘h’ at t.c:16:3:
/usr/include/bits/string3.h:53:10: warning: ‘__builtin___memcpy_chk’ writing 9 bytes into a region of size 8 overflows the destination [-Wstringop-overflow=]
   return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 3 Eric Gallager 2018-08-06 02:08:48 UTC
(In reply to Martin Sebor from comment #2)
> This is also affects overflowing buffers allocated by a user-defined
> function declared with attribute alloc_size.

Confirmed for this part too.
Comment 4 Martin Sebor 2019-08-28 21:52:28 UTC
See the related bug 91582.  I should handle both in the same fix.
Comment 5 Martin Sebor 2019-11-08 22:15:31 UTC
With the initial patch for pr91582 GCC issues the following warnings for the test case in comment #0:

$ gcc -O2 -S -Wall -Wextra pr79016.c 
pr79016.c: In function ‘fauto’:
pr79016.c:7:3: warning: ‘__builtin_memset’ forming offset [3, 4] is out of the bounds [0, 3] of object ‘d’ with type ‘char[3]’ [-Warray-bounds]
    7 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c:5:8: note: ‘d’ declared here
    5 |   char d[3];
      |        ^
pr79016.c: In function ‘funnamed’:
pr79016.c:12:3: warning: ‘__builtin_memset’ forming offset [3, 4] is out of the bounds [0, 3] of object ‘({anonymous})’ with type ‘char[3]’ [-Warray-bounds]
   12 |   f (__builtin_memset ((char[3]){ 0 }, 1, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c:12:33: note: ‘({anonymous})’ declared here
   12 |   f (__builtin_memset ((char[3]){ 0 }, 1, 5));
      |                                 ^
pr79016.c: In function ‘falloca’:
pr79016.c:19:3: warning: ‘__builtin_memset’ forming offset [3, 4] is out of the bounds [0, 3] [-Warray-bounds]
   19 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘fmalloc’:
pr79016.c:26:3: warning: ‘__builtin_memset’ forming offset [3, 4] is out of the bounds [0, 3] [-Warray-bounds]
   26 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘fvla’:
pr79016.c:36:3: warning: ‘__builtin_memset’ forming offset [3, 4] is out of the bounds [0, 3] [-Warray-bounds]
   36 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


With -Wno-array-bounds the warning become more meaningful:

pr79016.c: In function ‘fauto’:
pr79016.c:7:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 overflows the destination [-Wstringop-overflow=]
    7 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘funnamed’:
pr79016.c:12:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 overflows the destination [-Wstringop-overflow=]
   12 |   f (__builtin_memset ((char[3]){ 0 }, 1, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘falloca’:
pr79016.c:19:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 overflows the destination [-Wstringop-overflow=]
   19 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘fmalloc’:
pr79016.c:26:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 overflows the destination [-Wstringop-overflow=]
   26 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘fvla’:
pr79016.c:36:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 overflows the destination [-Wstringop-overflow=]
   36 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 6 Martin Sebor 2020-04-22 21:03:18 UTC
Fixed in GCC 10 which now issues the warnings below by default (without -Wall or other options):

pr79016.c: In function ‘fauto’:
pr79016.c:7:3: warning: ‘__builtin_memset’ forming offset [3, 4] is out of the bounds [0, 3] of object ‘d’ with type ‘char[3]’ [-Warray-bounds]
    7 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c:5:8: note: ‘d’ declared here
    5 |   char d[3];
      |        ^
pr79016.c: In function ‘funnamed’:
pr79016.c:12:3: warning: ‘__builtin_memset’ forming offset [3, 4] is out of the bounds [0, 3] of object ‘({anonymous})’ with type ‘char[3]’ [-Warray-bounds]
   12 |   f (__builtin_memset ((char[3]){ 0 }, 1, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c:12:33: note: ‘({anonymous})’ declared here
   12 |   f (__builtin_memset ((char[3]){ 0 }, 1, 5));
      |                                 ^
pr79016.c: In function ‘falloca’:
pr79016.c:19:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 [-Wstringop-overflow=]
   19 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c:17:13: note: at offset 0 to an object with size 3 allocated by ‘__builtin_alloca’ here
   17 |   char *d = __builtin_alloca (3);
      |             ^~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘fmalloc’:
pr79016.c:26:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size 3 [-Wstringop-overflow=]
   26 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c:24:13: note: at offset 0 to an object with size 3 allocated by ‘__builtin_malloc’ here
   24 |   char *d = __builtin_malloc (3);
      |             ^~~~~~~~~~~~~~~~~~~~
pr79016.c: In function ‘fvla’:
pr79016.c:36:3: warning: ‘__builtin_memset’ writing 5 bytes into a region of size between 0 and 3 [-Wstringop-overflow=]
   36 |   f (__builtin_memset (d, 0, 5));
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr79016.c:34:8: note: at offset 0 to an object with size at most 3 declared here
   34 |   char d [n];
      |        ^