1  /* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */
       2  
       3  /* There need to be at least two calls to a function for the
       4     call-summarization code to be used.
       5     TODO: add some kind of test that summarization *was* used.  */
       6  
       7  #include <stdlib.h>
       8  #include <string.h>
       9  #include "analyzer-decls.h"
      10  
      11  int *malloc_int (int i)
      12  {
      13    int *res = malloc (sizeof (int));
      14    if (!res)
      15      return NULL;
      16    *res = i;
      17    return res;
      18  }
      19  
      20  void test_malloc_int (int x)
      21  {
      22    int *p, *q;
      23  
      24    p = malloc_int (42);
      25    if (p)
      26      __analyzer_eval (*p == 42); /* { dg-warning "TRUE" } */
      27    free (p);
      28  
      29    q = malloc_int (x);
      30    if (q)
      31      __analyzer_eval (*q == x); /* { dg-warning "TRUE" } */
      32    free (q);
      33  }
      34  
      35  void test_leak (int x)
      36  {
      37    int *p = malloc_int (x); /* { dg-message "when 'malloc_int' returns pointer to heap-allocated buffer" } */
      38  } /* { dg-message "leak of 'p'" } */
      39  
      40  void *wrapped_malloc (size_t sz)
      41  {
      42    return malloc (sz);
      43  }
      44  
      45  void wrapped_free (void *p)
      46  {
      47    free (p);
      48  }
      49  
      50  void test_wrapped_malloc_and_free (size_t sz)
      51  {
      52    void *p = wrapped_malloc (100);
      53    void *q = wrapped_malloc (sz);
      54    __analyzer_dump_capacity (p); /* { dg-warning "capacity: '\\(\[^\n\r\]*\\)100'" } */
      55    __analyzer_dump_capacity (q); /* { dg-warning "capacity: 'INIT_VAL\\(sz_\[^\n\r\]*\\)'" } */
      56    wrapped_free (p);
      57    wrapped_free (q);
      58  }
      59  
      60  void test_use_after_free (void)
      61  {
      62    // TODO
      63  }
      64  
      65  void test_use_without_check (size_t sz)
      66  {
      67    char *buf = wrapped_malloc (sz); /* { dg-message "this call could return NULL" } */
      68    memset (buf, 'x', sz); /* { dg-warning "use of possibly-NULL 'buf' where non-null expected" } */
      69    wrapped_free (buf);
      70  }
      71  
      72  void test_out_of_bounds (size_t sz)
      73  {
      74    char *buf = wrapped_malloc (sz);
      75    if (!buf)
      76      return;
      77    memset (buf, 'x', sz);
      78    buf[sz] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
      79    wrapped_free (buf);
      80  }