Bug 93708 - missing warning on memset overflow with transposed arguments
Summary: missing warning on memset overflow with transposed arguments
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wstringop-overflow
  Show dependency treegraph
 
Reported: 2020-02-12 16:46 UTC by Martin Sebor
Modified: 2020-02-13 08:01 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 2020-02-12 16:46:08 UTC
GCC diagnoses some suspicious memset calls whose last two arguments look like they may have been transposed by -Wmemset-transposed-args just as long as the last argument is zero.

But it doesn't diagnose other similarly suspicious calls with a non-zero last argument.  What's more, it silently folds away such calls even if they write past the end of the object, replacing them with stores to the object itself (if possible).  Folding buffer overflows away may be a reasonable strategy in some cases but it's certainly the wrong thing to do with no warning in cases where the in-bounds store most likely ends up setting the data to the wrong (transposed) value.

The buffer overflow here should be diagnosed regardless of whether or not it's eliminated.  In addition, it might be worth to also consider enhancing -Wmemset-transposed-args to diagnose even calls with a non-zero last argument.

$ cat z.c && gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout z.c
void f (int, ...);

struct S { int x, y, z; };

void f0 (void)
{
  struct S *p = __builtin_alloca (sizeof *p);

  __builtin_memset (p, sizeof *p, 0);    // -Wmemset-transposed-args
  f (p->x, p->y, p->z);                  // missing -Wuninitialized
}

void f1 (void)
{
  struct S s;
  __builtin_memset (&s, sizeof s, -1);   // missing warning
  f (s.x, s.y, s.z);
}
z.c: In function ‘f0’:
z.c:9:3: warning: ‘memset’ used with constant zero length parameter; this could be due to transposed parameters [-Wmemset-transposed-args]
    9 |   __builtin_memset (p, sizeof *p, 0);    // -Wmemset-transposed-args
      |   ^~~~~~~~~~~~~~~~

;; Function f0 (f0, funcdef_no=0, decl_uid=1936, cgraph_uid=1, symbol_order=0)

f0 ()
{
  struct S * p;
  int _1;
  int _2;
  int _3;

  <bb 2> [local count: 1073741824]:
  p_6 = __builtin_alloca (12);
  _1 = p_6->z;
  _2 = p_6->y;
  _3 = p_6->x;
  f (_3, _2, _1);
  return;

}



;; Function f1 (f1, funcdef_no=1, decl_uid=1940, cgraph_uid=2, symbol_order=1)

f1 ()
{
  <bb 2> [local count: 1073741824]:
  f (202116108, 202116108, 202116108); [tail call]
  return;

}