1 /* Verify that accessing freed objects by built-in functions is diagnosed.
2 { dg-do compile }
3 { dg-options "-Wall" } */
4
5 typedef __SIZE_TYPE__ size_t;
6
7 #if __cplusplus
8 # define EXTERN_C extern "C"
9 #else
10 # define EXTERN_C extern
11 #endif
12
13 EXTERN_C void free (void*);
14 EXTERN_C void* realloc (void*, size_t);
15
16 EXTERN_C void* memcpy (void*, const void*, size_t);
17 EXTERN_C char* strcpy (char*, const char*);
18 EXTERN_C size_t strlen (const char*);
19
20
21 void sink (void*, ...);
22
23 struct Member { char *p; char a[4]; };
24
25 int nowarn_strcpy_memptr (struct Member *p)
26 {
27 char *q = strcpy (p->p, p->a);
28 free (p);
29 return *q;
30 }
31
32 int nowarn_strlen_memptr (struct Member *p)
33 {
34 const char *q = p->p;
35
36 free (p);
37
38 return strlen (q);
39 }
40
41 int warn_strlen_memptr (struct Member *p)
42 {
43 free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
44 return strlen (p->p); // { dg-warning "-Wuse-after-free" }
45 }
46
47 int warn_strlen_memarray (struct Member *p)
48 {
49 {
50 free (p);
51 return strlen (p->a); // { dg-warning "-Wuse-after-free" }
52 }
53
54 {
55 char *q = p->a;
56
57 free (p);
58 return strlen (q); // { dg-warning "-Wuse-after-free" "pr??????" { xfail *-*-* } }
59 }
60 }
61
62 void* nowarn_realloc_success (void *p)
63 {
64 void *q = realloc (p, 7);
65 if (!q)
66 /* When realloc fails the original pointer remains valid. */
67 return p;
68
69 return q;
70 }
71
72 void* nowarn_realloc_equal (void *p, int *moved)
73 {
74 void *q = realloc (p, 7);
75 /* Verify that equality is not diagnosed at the default level
76 (it is diagnosed at level 3). */
77 *moved = !(p == q);
78 return q;
79 }
80
81 void* nowarn_realloc_unequal (void *p, int *moved)
82 {
83 void *q = realloc (p, 7);
84 /* Verify that inequality is not diagnosed at the default level
85 (it is diagnosed at level 3). */
86 *moved = p != q;
87 return q;
88 }
89
90 void* warn_realloc_relational (void *p, int *rel)
91 {
92 void *q = realloc (p, 7); // { dg-message "call to '\(void\\* \)?realloc\(\\(void\\*, size_t\\)\)?'" "note" }
93 /* Verify that all relational expressions are diagnosed at the default
94 level. */
95 rel[0] = (char*)p < (char*)q; // { dg-warning "-Wuse-after-free" }
96 rel[1] = (char*)p <= (char*)q; // { dg-warning "-Wuse-after-free" }
97 rel[2] = (char*)p >= (char*)q; // { dg-warning "-Wuse-after-free" }
98 rel[3] = (char*)p > (char*)q; // { dg-warning "-Wuse-after-free" }
99 return q;
100 }
101
102 void* warn_realloc_unchecked (void *p, int *moved)
103 {
104 void *q = realloc (p, 7); // { dg-message "call to '\(void\\* \)?realloc\(\\(void\\*, size_t\\)\)?'" "note" }
105 /* Use subtraction rather than inequality to trigger the warning
106 at the default level (equality is diagnosed only at level 3). */
107 *moved = (char*)p - (char*)q; // { dg-warning "-Wuse-after-free" }
108 return q;
109 }
110
111 void* nowarn_realloc_unchecked_copy (void *p1, void *p2, const void *s,
112 int n, int *x)
113 {
114 void *p3 = memcpy (p1, s, n);
115 void *p4 = realloc (p2, 7);
116 *x = p3 != p4;
117 return p4;
118 }
119
120 void* warn_realloc_unchecked_copy (void *p, const void *s, int n, int *moved)
121 {
122 void *p2 = memcpy (p, s, n);
123 void *q = realloc (p, 7); // { dg-message "call to '\(void\\* \)?realloc\(\\(void\\*, size_t\\)\)?'" "note" }
124 *moved = (char*)p2 - (char*)q; // { dg-warning "-Wuse-after-free" }
125 return q;
126 }
127
128 void* warn_realloc_failed (void *p, int *moved)
129 {
130 void *q = realloc (p, 7); // { dg-message "call to '\(void\\* \)?realloc\(\\(void\\*, size_t\\)\)?'" "note" }
131 if (q)
132 {
133 /* When realloc succeeds the original pointer is invalid. */
134 *moved = (char*)p - (char*)q; // { dg-warning "-Wuse-after-free" }
135 return q;
136 }
137
138 return p;
139 }
140
141 extern void *evp;
142
143 void* warn_realloc_extern (void *p, int *moved)
144 {
145 evp = realloc (p, 7);
146 if (evp)
147 {
148 /* When realloc succeeds the original pointer is invalid. */
149 *moved = (char*)p - (char*)evp; // { dg-warning "-Wuse-after-free" "escaped" }
150 return evp;
151 }
152
153 return p; // { dg-bogus "-Wuse-after-free" "safe use after realloc failure" { xfail *-*-* } }
154 }
155
156 struct A { void *p, *q; int moved; };
157
158 void* warn_realloc_arg (struct A *p)
159 {
160 p->q = realloc (p->p, 7);
161 if (p->q)
162 {
163 /* When realloc succeeds the original pointer is invalid. */
164 p->moved = p->p != p->q; // { dg-warning "-Wuse-after-free" "escaped" { xfail *-*-* } }
165 return p->q;
166 }
167
168 return p->p;
169 }