(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
realloc-2.c
       1  /* { dg-additional-options "-fno-analyzer-suppress-followups" } */
       2  
       3  #include "analyzer-decls.h"
       4  
       5  typedef __SIZE_TYPE__ size_t;
       6  
       7  #define NULL ((void *)0)
       8  
       9  extern void *malloc (size_t __size)
      10    __attribute__ ((__nothrow__ , __leaf__))
      11    __attribute__ ((__malloc__))
      12    __attribute__ ((__alloc_size__ (1)));
      13  extern void *realloc (void *__ptr, size_t __size)
      14    __attribute__ ((__nothrow__ , __leaf__))
      15    __attribute__ ((__warn_unused_result__))
      16    __attribute__ ((__alloc_size__ (2)));
      17  extern void free (void *__ptr)
      18    __attribute__ ((__nothrow__ , __leaf__));
      19  
      20  char *test_8 (size_t sz)
      21  {
      22    char *p, *q;
      23  
      24    p = malloc (3);
      25    if (!p)
      26      return NULL;
      27  
      28    __analyzer_dump_capacity (p); /* { dg-warning "capacity: '\\(size_t\\)3'" } */
      29  
      30    p[0] = 'a';
      31    p[1] = 'b';
      32    p[2] = 'c';
      33  
      34    __analyzer_eval (p[0] == 'a'); /* { dg-warning "TRUE" } */
      35    __analyzer_eval (p[1] == 'b'); /* { dg-warning "TRUE" } */
      36    __analyzer_eval (p[2] == 'c'); /* { dg-warning "TRUE" } */
      37  
      38    q = realloc (p, 6);
      39  
      40    /* We should have 3 nodes, corresponding to "failure",
      41       "success without moving", and "success with moving".  */
      42    __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */
      43    
      44    if (q)
      45      {
      46        __analyzer_dump_capacity (q); /* { dg-warning "capacity: '\\(size_t\\)6'" } */
      47        q[3] = 'd';
      48        q[4] = 'e';
      49        q[5] = 'f';
      50        if (q == p)
      51  	{
      52  	  /* "realloc" success, growing the buffer in-place.  */
      53  	  __analyzer_eval (p[0] == 'a'); /* { dg-warning "TRUE" } */
      54  	  __analyzer_eval (p[1] == 'b'); /* { dg-warning "TRUE" } */
      55  	  __analyzer_eval (p[2] == 'c'); /* { dg-warning "TRUE" } */
      56  	  // TODO
      57  	}
      58        else
      59  	{
      60  	  /* "realloc" success, moving the buffer (and thus freeing "p").  */
      61  	  __analyzer_eval (q[0] == 'a'); /* { dg-warning "TRUE" } */
      62  	  __analyzer_eval (q[1] == 'b'); /* { dg-warning "TRUE" } */
      63  	  __analyzer_eval (q[2] == 'c'); /* { dg-warning "TRUE" } */
      64  	  __analyzer_eval (p[0] == 'a'); /* { dg-warning "UNKNOWN" "unknown" } */
      65  	  /* { dg-warning "use after 'free' of 'p'" "use after free" { target *-*-* } .-1 } */
      66  	}
      67        __analyzer_eval (q[3] == 'd'); /* { dg-warning "TRUE" } */
      68        __analyzer_eval (q[4] == 'e'); /* { dg-warning "TRUE" } */
      69        __analyzer_eval (q[5] == 'f'); /* { dg-warning "TRUE" } */
      70      }
      71    else
      72      {
      73        /* "realloc" failure.  p should be unchanged.  */
      74        __analyzer_dump_capacity (p); /* { dg-warning "capacity: '\\(size_t\\)3'" } */
      75        __analyzer_eval (p[0] == 'a'); /* { dg-warning "TRUE" } */
      76        __analyzer_eval (p[1] == 'b'); /* { dg-warning "TRUE" } */
      77        __analyzer_eval (p[2] == 'c'); /* { dg-warning "TRUE" } */
      78        return p;
      79      }
      80  
      81    return q;
      82  }