This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug tree-optimization/80532] New: warning on pointer access after free


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

            Bug ID: 80532
           Summary: warning on pointer access after free
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

Using the value of a pointer that points to an object whose lifetime has ended
is undefined, and a common source of bugs.  In the following test case,
function free_list shows an example of one such bug (courtesy of Kernighan &
Ritchie) where a freed pointer is dereferenced.

Function foobar shows another example.  That example is interesting because it
shows that GCC is smart enough to eliminate the first call to memset (because
the lifetime of the object the pointer points ends with the subsequent call to
free) but it doesn't eliminate the second call to free or the second call to
memset, even though that operate on an object whose lifetime has ended and will
almost certainly corrupt the heap.  GCC also doesn't warn on those calls.  It
would be a useful feature if GCC did both: warn and eliminate the undefined
calls/accesses.


$ cat c.c && gcc -O2 -S -Wall -Wextra -Wpedantic
-fdump-tree-optimized=/dev/stdout c.c
#include <stdlib.h>
#include <string.h>

struct node { struct node *next; int value; };

void free_list (struct node *head)
{
  struct node *p;

  for (p = head; p != 0; p = p->next)
    free (p);
}

void foobar (void *p, unsigned n)
{
  memset (p, 0, n);
  free (p);
  free (p);
  memset (p, 0, n);
}

;; Function free_list (free_list, funcdef_no=14, decl_uid=2614, cgraph_uid=14,
symbol_order=14)

Removing basic block 5
Removing basic block 6
Removing basic block 7
Removing basic block 8
free_list (struct node * head)
{
  struct node * p;

  <bb 2> [15.00%]:
  if (head_3(D) != 0B)
    goto <bb 3>; [85.00%]
  else
    goto <bb 4>; [15.00%]

  <bb 3> [85.00%]:
  # p_9 = PHI <p_6(3), head_3(D)(2)>
  free (p_9);
  p_6 = p_9->next;
  if (p_6 != 0B)
    goto <bb 3>; [85.00%]
  else
    goto <bb 4>; [15.00%]

  <bb 4> [15.00%]:
  return;

}



;; Function foobar (foobar, funcdef_no=15, decl_uid=2622, cgraph_uid=15,
symbol_order=15)

foobar (void * p, unsigned int n)
{
  long unsigned int _1;

  <bb 2> [100.00%]:
  _1 = (long unsigned int) n_2(D);
  free (p_4(D));
  free (p_4(D));
  memset (p_4(D), 0, _1); [tail call]
  return;

}


tmp$

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]