(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
Wuse-after-free.c
       1  /* Exercise basic cases of -Wuse-after-free without optimization.
       2     { dg-do compile }
       3     { dg-options "-O0 -Wall" } */
       4  
       5  typedef __SIZE_TYPE__ size_t;
       6  
       7  #if __cplusplus
       8  #  define EXTERN_C extern "C"
       9  #else
      10  #  define EXTERN_C extern
      11  #endif
      12  
      13  EXTERN_C void* alloca (size_t);
      14  
      15  EXTERN_C void* calloc (size_t, size_t);
      16  EXTERN_C void* malloc (size_t);
      17  
      18  EXTERN_C void free (void*);
      19  
      20  
      21  void sink (void *);
      22  
      23  extern void* evp;
      24  extern void* evpa[];
      25  
      26  extern int ei;
      27  
      28  struct List { struct List *next; };
      29  
      30  void nowarn_free (void *vp, struct List *lp)
      31  {
      32    {
      33      free (vp);
      34      vp = 0;
      35      sink (vp);
      36    }
      37    {
      38      free (evp);
      39      evp = 0;
      40      sink (evp);
      41    }
      42    {
      43      free (evpa[0]);
      44      evpa[0] = 0;
      45      sink (evpa[0]);
      46    }
      47    {
      48      void *vp = evpa[0];
      49      free (evpa[1]);
      50      sink (vp);
      51    }
      52    {
      53      void *p = evpa[1];
      54      if (ei & 1)
      55        free (p);
      56      if (ei & 2)
      57        sink (p);
      58    }
      59    {
      60      struct List *next = lp->next;
      61      free (lp);
      62      free (next);
      63    }
      64  }
      65  
      66  void nowarn_free_arg (void *p, void *q)
      67  {
      68    free (p);
      69    if (q)
      70      free (q);
      71  }
      72  
      73  void nowarn_free_extern (void)
      74  {
      75    extern void *ep, *eq;
      76    free (ep);
      77    ep = eq;
      78    free (ep);
      79  }
      80  
      81  void nowarn_free_assign (void)
      82  {
      83    extern void *ep;
      84    free (ep);
      85    ep = 0;
      86    free (ep);
      87  }
      88  
      89  #pragma GCC diagnostic push
      90  /* Verify that -Wuse-after-free works with #pragma diagnostic.  Note
      91     that the option name should not need to include a trailing =, even
      92     though it's a multi-level option.  (specifying the level after
      93     the option, as in "-Wuse-after-free=2", doesn't work.  */
      94  #pragma GCC diagnostic ignored "-Wuse-after-free"
      95  
      96  void nowarn_double_free_suppressed (void *p)
      97  {
      98    free (p);
      99    free (p);
     100  }
     101  
     102  #pragma GCC diagnostic pop
     103  
     104  void warn_double_free_arg (void *p)
     105  {
     106    free (p);                   // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
     107    // Verify exactly one warning is issued.
     108    free (p);                   // { dg-warning "\\\-Wuse-after-free" }
     109                                // { dg-bogus "\\\-Wuse-after-free" "duplicate warning" { target *-*-* } .-1 }
     110  
     111  }
     112  
     113  void warn_double_free_extern (void)
     114  {
     115    /* GCC assumes free() clobbers global memory and the warning is
     116       too simplistic to see through that assumption.  */
     117    extern void *ep, *eq;
     118    {
     119      eq = ep;
     120      free (ep);                // { dg-message "call to 'free'" "pr??????" { xfail *-*-* } }
     121      free (eq);                // { dg-warning "\\\-Wuse-after-free" "pr??????" { xfail *-*-* } }
     122    }
     123  }
     124  
     125  void warn_deref_after_free (int *p, int i)
     126  {
     127    int *q0 = p, *q1 = p + 1, *qi = p + i;
     128    free (p);                   // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
     129    *p = 0;                     // { dg-warning "\\\-Wuse-after-free" }
     130  
     131    *q0 = 0;                    // { dg-warning "\\\-Wuse-after-free" }
     132    *q1 = 0;                    // { dg-warning "\\\-Wuse-after-free" }
     133    *qi = 0;                    // { dg-warning "\\\-Wuse-after-free" }
     134  }
     135  
     136  void warn_array_ref_after_free (int *p, int i)
     137  {
     138    free (p);                   // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
     139    p[i] = 0;                   // { dg-warning "\\\-Wuse-after-free" }
     140  }
     141  
     142  void nowarn_free_list (struct List *head)
     143  {
     144    for (struct List *p = head, *q; p; p = q)
     145      {
     146        q = p->next;
     147        free (p);
     148      }
     149  }
     150  
     151  void warn_free_list (struct List *head)
     152  {
     153    struct List *p = head;
     154    for (; p; p = p->next)      // { dg-warning "\\\[-Wuse-after-free" }
     155      free (p);                 // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
     156  }
     157  
     158  
     159  void warn_free (void *vp)
     160  {
     161    {
     162      free (vp);                // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
     163      evp = vp;                 // { dg-warning "-Wuse-after-free" }
     164      evpa[0] = vp;             // { dg-warning "-Wuse-after-free" }
     165      evpa[1] = evp;
     166    }
     167  }