1  /* Verify that the analyzer correctly purges state when it sees a call to
       2     an unknown function.  */
       3  
       4  #include <stdlib.h>
       5  
       6  /* Verify fix for false-positive when checking for CVE-2005-1689.  */
       7  
       8  typedef struct _krb5_data {
       9    char *data;
      10  } krb5_data;
      11  
      12  extern void krb5_read_message(krb5_data *buf);
      13  
      14  void
      15  test_1 (krb5_data inbuf)
      16  {
      17    free(inbuf.data);
      18    krb5_read_message(&inbuf); 
      19    free(inbuf.data); /* { dg-bogus "double-'free'" } */
      20  }
      21  
      22  /* Verify that __pure__ functions are treated as not having side-effects.  */
      23  
      24  extern int called_by_test_1a (void *)
      25    __attribute__ ((__pure__));
      26  void test_1a (krb5_data inbuf)
      27  {
      28    free (inbuf.data);
      29    called_by_test_1a (&inbuf);
      30    free (inbuf.data); /* { dg-warning "double-'free'" } */
      31  }
      32  
      33  /* Verify that global pointers can be affected by an unknown function.  */
      34  
      35  void *global_ptr;
      36  extern void unknown_side_effects (void);
      37  
      38  void test_2 (void)
      39  {
      40    free (global_ptr);
      41    unknown_side_effects ();
      42    free (global_ptr);
      43  }
      44  
      45  extern void called_by_test_3 (void *);
      46  
      47  void test_3a (void)
      48  {
      49    void *ptr = malloc (1024);
      50    called_by_test_3 (ptr);
      51  }  /* { dg-bogus "leak" } */
      52  
      53  void test_3b (void)
      54  {
      55    krb5_data k;
      56    k.data = malloc (1024);
      57    called_by_test_3 (&k);
      58  } /* { dg-bogus "leak" } */
      59  
      60  /* Verify that we traverse the graph of regions that are reachable from
      61     the call.  */
      62  
      63  struct foo
      64  {
      65    struct foo *next;
      66    int *ptr;
      67  };
      68  
      69  /* First, without a call to an unknown function.  */
      70  
      71  void test_4a (void)
      72  {
      73    struct foo node_a;
      74    struct foo node_b;
      75    node_a.next = &node_b;
      76    node_b.ptr = malloc (sizeof (int));
      77    global_ptr = &node_a;
      78    *node_b.ptr = 42; /* { dg-warning "possibly-NULL" "possibly-NULL" } */
      79    /* Although there's a chain of pointers to the allocation, pointed to
      80       by global_ptr, the chain goes through the stack frame and thus
      81       there's a leak when it is popped.  */
      82  } /* { dg-warning "leak of 'node_b.ptr'" } */
      83  
      84  /* With a call to an unknown function.  */
      85  
      86  void test_4b (void)
      87  {
      88    struct foo node_a;
      89    struct foo node_b;
      90    node_a.next = &node_b;
      91    node_b.ptr = malloc (sizeof (int));
      92    global_ptr = &node_a;
      93    unknown_side_effects (); /* everything potentially visible through global_ptr.  */
      94    *node_b.ptr = 42; /* { dg-bogus "possibly-NULL" } */
      95  } /* { dg-bogus "leak" } */
      96  
      97  extern void called_by_test_5 (const char *);
      98  void test_5 (void)
      99  {
     100    called_by_test_5 ("???");
     101  }
     102  
     103  extern void called_by_test_6 (const struct foo *);
     104  void test_6 (void)
     105  {
     106    struct foo node;
     107    node.next = NULL;
     108    node.ptr = malloc (sizeof (int));
     109  
     110    /* This is a const ptr, but struct foo's ptr is non-const,
     111       so we ought to assume it could be written to.  */
     112    called_by_test_6 (&node);
     113  } /* { dg-bogus "leak" } */
     114  
     115  /* TODO: things reachable from "outside" i.e. by params to caller to entrypoint.  */