(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
malloc-callbacks.c
       1  /* { dg-require-effective-target alloca } */
       2  
       3  #include <stdlib.h>
       4  
       5  typedef void *(*allocator_t) (size_t);
       6  typedef void (*deallocator_t) (void *);
       7  
       8  static allocator_t __attribute__((noinline))
       9  get_malloc (void)
      10  {
      11    return malloc;
      12  }
      13  
      14  static allocator_t __attribute__((noinline))
      15  get_alloca (void)
      16  {
      17    /* On e.g. Solaris, alloca is a macro so we can't take its address;
      18       use __builtin_alloca instead.  */
      19    return __builtin_alloca;
      20  }
      21  
      22  static deallocator_t __attribute__((noinline))
      23  get_free (void)
      24  {
      25    return free;
      26  }
      27  
      28  void test_1 (void *ptr)
      29  {
      30    deallocator_t dealloc_fn = free;
      31    dealloc_fn (ptr); /* { dg-message "first 'free' here" } */
      32    dealloc_fn (ptr); /* { dg-warning "double-'free'" } */
      33  }
      34  
      35  void test_2 (void *ptr)
      36  {
      37    deallocator_t dealloc_fn = get_free ();
      38    dealloc_fn (ptr); /* { dg-message "first 'free' here" } */
      39    dealloc_fn (ptr); /* { dg-warning "double-'free'" } */
      40  }
      41  
      42  static void __attribute__((noinline))
      43  called_by_test_3 (void *ptr, deallocator_t dealloc_fn)
      44  {
      45    dealloc_fn (ptr); /* { dg-warning "double-'free'" } */
      46  }
      47  
      48  void test_3 (void *ptr)
      49  {
      50    called_by_test_3 (ptr, free);
      51    called_by_test_3 (ptr, free);
      52  }
      53  
      54  int *test_4 (void)
      55  {
      56    allocator_t alloc_fn = get_malloc ();
      57    int *ptr = alloc_fn (sizeof (int)); /* { dg-message "this call could return NULL" } */
      58    *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr'" } */
      59    return ptr;
      60  }
      61  
      62  int *test_5 (void)
      63  {
      64    allocator_t alloc_fn = get_alloca ();
      65    deallocator_t dealloc_fn = get_free ();
      66    int *ptr = alloc_fn (sizeof (int)); /* dg-message "region created on stack here" } */
      67    dealloc_fn (ptr); /* { dg-warning "'free' of 'ptr' which points to memory on the stack" } */
      68  }
      69  
      70  static void __attribute__((noinline))
      71  called_by_test_6a (void *ptr)
      72  {
      73    free (ptr); /* { dg-warning "double-'free'" } */
      74  }
      75  
      76  static deallocator_t __attribute__((noinline))
      77  called_by_test_6b (void)
      78  {
      79    return called_by_test_6a;
      80  }
      81  
      82  void test_6 (void *ptr)
      83  {
      84    deallocator_t dealloc_fn = called_by_test_6b ();
      85    dealloc_fn (ptr);
      86    dealloc_fn (ptr);
      87  }