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

            Bug ID: 82867
           Summary: missing warning on buffer overflow assigning to the
                    result of mempcpy
           Product: gcc
           Version: 8.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 test case was inspired by Glibc bug
https://sourceware.org/bugzilla/show_bug.cgi?id=22332.  Although the mempcpy
call in it doesn't overflow, the assignment via the pointer returned by it
does.  It seems that it should be possible to enhance the -Wstringop-overflow
warning to detect this case (perhaps in tree-ssa-strlen.c?) even though the
value of n is unknown, by saving the alloca/malloc argument for each allocated
block. checking it against the mempcpy byte counter in assignments through the
returned pointer, and diagnosing it if it's the same.

$ cat c.c && gcc -O2 -S -Wall -Wextra -fdump-tree-strlen=/dev/stdout c.c

void* f (const char *s0, const char *s1)
{
  void *d = __builtin_malloc (s1 - s0);
  *(char*)__builtin_mempcpy (d, s0, s1 - s0) = '\0';
  return d;
}

void sink (void*);

void g (const char *s0, const char *s1)
{
  void *d = __builtin_alloca (s1 - s0);
  *(char*)__builtin_mempcpy (d, s0, s1 - s0) = '\0';
  sink (d);
}


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

f (const char * s0, const char * s1)
{
  void * d;
  long int s1.0_1;
  long int s0.1_2;
  long int _3;
  long unsigned int _4;
  void * _5;

  <bb 2> [100.00%] [count: INV]:
  s1.0_1 = (long int) s1_6(D);
  s0.1_2 = (long int) s0_7(D);
  _3 = s1.0_1 - s0.1_2;
  _4 = (long unsigned int) _3;
  d_10 = __builtin_malloc (_4);
  _5 = __builtin_mempcpy (d_10, s0_7(D), _4);
  MEM[(char *)_5] = 0;
  return d_10;

}



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

g (const char * s0, const char * s1)
{
  void * d;
  long int s1.4_1;
  long int s0.5_2;
  long int _3;
  long unsigned int _4;
  void * _5;

  <bb 2> [100.00%] [count: INV]:
  s1.4_1 = (long int) s1_6(D);
  s0.5_2 = (long int) s0_7(D);
  _3 = s1.4_1 - s0.5_2;
  _4 = (long unsigned int) _3;
  d_10 = __builtin_alloca (_4);
  _5 = __builtin_mempcpy (d_10, s0_7(D), _4);
  MEM[(char *)_5] = 0;
  sink (d_10);
  return;

}

Reply via email to