Bug Summary

File:clientwin.c
Location:line 223, column 20
Description:Potential leak of memory pointed to by 'roots'

Annotated Source Code

1/*
2 * Copyright 2007 Kim woelders
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22#include <xcb/xcb.h>
23#include <xcb/xproto.h>
24
25#include <stdlib.h>
26#include <string.h>
27
28#include "clientwin.h"
29#include "dsimple.h"
30
31static xcb_atom_t atom_wm_state = XCB_ATOM_NONE;
32
33/*
34 * Check if window has given property
35 */
36static Bool
37Window_Has_Property(xcb_connection_t * dpy, xcb_window_t win, xcb_atom_t atom)
38{
39 xcb_get_property_cookie_t prop_cookie;
40 xcb_get_property_reply_t *prop_reply;
41
42 prop_cookie = xcb_get_property (dpy, False, win, atom,
43 XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
44
45 prop_reply = xcb_get_property_reply (dpy, prop_cookie, NULL((void *)0));
46
47 if (prop_reply) {
48 xcb_atom_t reply_type = prop_reply->type;
49 free (prop_reply);
50 if (reply_type != XCB_NONE0L)
51 return True;
52 }
53
54 return False;
55}
56
57/*
58 * Check if window is viewable
59 */
60static Bool
61Window_Is_Viewable(xcb_connection_t * dpy, xcb_window_t win)
62{
63 Bool ok = False;
64 xcb_get_window_attributes_cookie_t attr_cookie;
65 xcb_get_window_attributes_reply_t *xwa;
66
67 attr_cookie = xcb_get_window_attributes (dpy, win);
68 xwa = xcb_get_window_attributes_reply (dpy, attr_cookie, NULL((void *)0));
69
70 if (xwa) {
71 ok = (xwa->_class == XCB_WINDOW_CLASS_INPUT_OUTPUT) &&
72 (xwa->map_state == XCB_MAP_STATE_VIEWABLE);
73 free (xwa);
74 }
75
76 return ok;
77}
78
79/*
80 * Find a window that has WM_STATE set in the window tree below win.
81 * Unmapped/unviewable windows are not considered valid matches.
82 * Children are searched in top-down stacking order.
83 * The first matching window is returned, None if no match is found.
84 */
85static xcb_window_t
86Find_Client_In_Children(xcb_connection_t * dpy, xcb_window_t win)
87{
88 xcb_query_tree_cookie_t qt_cookie;
89 xcb_query_tree_reply_t *tree;
90 xcb_window_t *children;
91 unsigned int n_children;
92 int i;
93
94 qt_cookie = xcb_query_tree (dpy, win);
95 tree = xcb_query_tree_reply (dpy, qt_cookie, NULL((void *)0));
96 if (!tree)
97 return XCB_WINDOW_NONE;
98 n_children = xcb_query_tree_children_length (tree);
99 if (!n_children) {
100 free (tree);
101 return XCB_WINDOW_NONE;
102 }
103 children = xcb_query_tree_children (tree);
104
105 /* Check each child for WM_STATE and other validity */
106 win = XCB_WINDOW_NONE;
107 for (i = (int) n_children - 1; i >= 0; i--) {
108 if (!Window_Is_Viewable(dpy, children[i])) {
109 /* Don't bother descending into this one */
110 children[i] = XCB_WINDOW_NONE;
111 continue;
112 }
113 if (!Window_Has_Property(dpy, children[i], atom_wm_state))
114 continue;
115
116 /* Got one */
117 win = children[i];
118 goto done;
119 }
120
121 /* No children matched, now descend into each child */
122 for (i = (int) n_children - 1; i >= 0; i--) {
123 if (children[i] == XCB_WINDOW_NONE)
124 continue;
125 win = Find_Client_In_Children(dpy, children[i]);
126 if (win != XCB_WINDOW_NONE)
127 break;
128 }
129
130 done:
131 free (tree); /* includes children */
132
133 return win;
134}
135
136/*
137 * Find virtual roots (_NET_VIRTUAL_ROOTS)
138 */
139static xcb_window_t *
140Find_Roots(xcb_connection_t * dpy, xcb_window_t root, unsigned int *num)
141{
142 xcb_atom_t atom_virtual_root;
143
144 xcb_get_property_cookie_t prop_cookie;
145 xcb_get_property_reply_t *prop_reply;
146
147 xcb_window_t *prop_ret = NULL((void *)0);
148
149 *num = 0;
150
151 atom_virtual_root = Get_Atom (dpy, "_NET_VIRTUAL_ROOTS");
152 if (atom_virtual_root == XCB_ATOM_NONE)
2
Assuming 'atom_virtual_root' is not equal to XCB_ATOM_NONE
3
Taking false branch
153 return NULL((void *)0);
154
155 prop_cookie = xcb_get_property (dpy, False, root, atom_virtual_root,
156 XCB_ATOM_WINDOW, 0, 0x7fffffff);
157 prop_reply = xcb_get_property_reply (dpy, prop_cookie, NULL((void *)0));
158 if (!prop_reply)
4
Assuming 'prop_reply' is non-null
5
Taking false branch
159 return NULL((void *)0);
160
161 if ((prop_reply->value_len > 0) && (prop_reply->type == XCB_ATOM_WINDOW)
6
Taking true branch
162 && (prop_reply->format == 32)) {
163 int length = xcb_get_property_value_length (prop_reply);
164 prop_ret = malloc(length);
7
Memory is allocated
165 if (prop_ret) {
8
Assuming 'prop_ret' is non-null
9
Taking true branch
166 memcpy (prop_ret, xcb_get_property_value(prop_reply), length)__builtin___memcpy_chk (prop_ret, xcb_get_property_value(prop_reply
), length, __builtin_object_size (prop_ret, 0))
;
167 *num = prop_reply->value_len;
168 }
169 }
170 free (prop_reply);
171
172 return prop_ret;
173}
174
175/*
176 * Find child window at pointer location
177 */
178static xcb_window_t
179Find_Child_At_Pointer(xcb_connection_t * dpy, xcb_window_t win)
180{
181 xcb_window_t child_return = XCB_WINDOW_NONE;
182
183 xcb_query_pointer_cookie_t qp_cookie;
184 xcb_query_pointer_reply_t *qp_reply;
185
186 qp_cookie = xcb_query_pointer (dpy, win);
187 qp_reply = xcb_query_pointer_reply (dpy, qp_cookie, NULL((void *)0));
188
189 if (qp_reply) {
190 child_return = qp_reply->child;
191 free (qp_reply);
192 }
193
194 return child_return;
195}
196
197/*
198 * Find client window at pointer location
199 *
200 * root is the root window.
201 * subwin is the subwindow reported by a ButtonPress event on root.
202 *
203 * If the WM uses virtual roots subwin may be a virtual root.
204 * If so, we descend the window stack at the pointer location and assume the
205 * child is the client or one of its WM frame windows.
206 * This will of course work only if the virtual roots are children of the real
207 * root.
208 */
209xcb_window_t
210Find_Client(xcb_connection_t * dpy, xcb_window_t root, xcb_window_t subwin)
211{
212 xcb_window_t *roots;
213 unsigned int i, n_roots;
214 xcb_window_t win;
215
216 /* Check if subwin is a virtual root */
217 roots = Find_Roots(dpy, root, &n_roots);
1
Calling 'Find_Roots'
10
Returned allocated memory
218 for (i = 0; i < n_roots; i++) {
11
Loop condition is true. Entering loop body
219 if (subwin != roots[i])
12
Taking false branch
220 continue;
221 win = Find_Child_At_Pointer(dpy, subwin);
222 if (win == XCB_WINDOW_NONE)
13
Taking true branch
223 return subwin; /* No child - Return virtual root. */
14
Potential leak of memory pointed to by 'roots'
224 subwin = win;
225 break;
226 }
227 free (roots);
228
229 if (atom_wm_state == XCB_ATOM_NONE) {
230 atom_wm_state = Get_Atom(dpy, "WM_STATE");
231 if (atom_wm_state == XCB_ATOM_NONE)
232 return subwin;
233 }
234
235 /* Check if subwin has WM_STATE */
236 if (Window_Has_Property(dpy, subwin, atom_wm_state))
237 return subwin;
238
239 /* Attempt to find a client window in subwin's children */
240 win = Find_Client_In_Children(dpy, subwin);
241 if (win != XCB_WINDOW_NONE)
242 return win; /* Found a client */
243
244 /* Did not find a client */
245 return subwin;
246}