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
test_1(krb5_data inbuf)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__));
test_1a(krb5_data inbuf)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 
test_2(void)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 
test_3a(void)47 void test_3a (void)
48 {
49   void *ptr = malloc (1024);
50   called_by_test_3 (ptr);
51 }  /* { dg-bogus "leak" } */
52 
test_3b(void)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 
test_4a(void)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   /* { dg-warning "leak" "leak" { target *-*-* } .-1 } */
80   /* FIXME: the above leak report is correct, but is reported at the wrong
81      location.  */
82 } /* { dg-warning "leak" } */
83 
84 /* With a call to an unknown function.  */
85 
test_4b(void)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 *);
test_5(void)98 void test_5 (void)
99 {
100   called_by_test_5 ("???");
101 }
102 
103 extern void called_by_test_6 (const struct foo *);
test_6(void)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.  */
116