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