Bug Summary

File:Xge.c
Location:line 152, column 20
Description:Use of memory after it is freed

Annotated Source Code

1/*
2 * Copyright © 2007-2008 Peter Hutterer
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Peter Hutterer, University of South Australia, NICTA
24 */
25
26/*
27 * XGE is an extension to re-use a single opcode for multiple events,
28 * depending on the extension. XGE allows events >32 bytes.
29 */
30
31#ifdef HAVE_CONFIG_H1
32#include <config.h>
33#endif
34
35#include <stdio.h>
36#include <X11/extensions/geproto.h>
37#include <X11/extensions/ge.h>
38#include <X11/Xlibint.h>
39#include <X11/extensions/extutil.h>
40#include <X11/extensions/Xge.h>
41
42/***********************************************************************/
43/* internal data structures */
44/***********************************************************************/
45
46typedef struct {
47 int present;
48 short major_version;
49 short minor_version;
50} XGEVersionRec;
51
52/* NULL terminated list of registered extensions. */
53typedef struct _XGEExtNode {
54 int extension;
55 XExtensionHooks* hooks;
56 struct _XGEExtNode* next;
57} XGEExtNode, *XGEExtList;
58
59/* Internal data for GE extension */
60typedef struct _XGEData {
61 XEvent data;
62 XGEVersionRec *vers;
63 XGEExtList extensions;
64} XGEData;
65
66
67/* forward declarations */
68static XExtDisplayInfo* _xgeFindDisplay(Display*);
69static Boolint _xgeWireToEvent(Display*, XEvent*, xEvent*);
70static Statusint _xgeEventToWire(Display*, XEvent*, xEvent*);
71static int _xgeDpyClose(Display*, XExtCodes*);
72static XGEVersionRec* _xgeGetExtensionVersion(Display*,
73 _Xconstconst char*,
74 XExtDisplayInfo*);
75static Boolint _xgeCheckExtension(Display* dpy, XExtDisplayInfo* info);
76
77/* main extension information data */
78static XExtensionInfo *xge_info;
79static const char xge_extension_name[] = GE_NAME"Generic Event Extension";
80static XExtensionHooks xge_extension_hooks = {
81 NULL((void*)0), /* create_gc */
82 NULL((void*)0), /* copy_gc */
83 NULL((void*)0), /* flush_gc */
84 NULL((void*)0), /* free_gc */
85 NULL((void*)0), /* create_font */
86 NULL((void*)0), /* free_font */
87 _xgeDpyClose, /* close_display */
88 _xgeWireToEvent, /* wire_to_event */
89 _xgeEventToWire, /* event_to_wire */
90 NULL((void*)0), /* error */
91 NULL((void*)0), /* error_string */
92};
93
94
95static XExtDisplayInfo *_xgeFindDisplay(Display *dpy)
96{
97 XExtDisplayInfo *dpyinfo;
98 if (!xge_info)
99 {
100 if (!(xge_info = XextCreateExtension()))
101 return NULL((void*)0);
102 }
103 if (!(dpyinfo = XextFindDisplay (xge_info, dpy)))
104 {
105 dpyinfo = XextAddDisplay (xge_info,
106 dpy,
107 xge_extension_name,
108 &xge_extension_hooks,
109 0 /* no events, see below */,
110 NULL((void*)0));
111 /* dpyinfo->codes is only null if the server claims not to suppport
112 XGE. Don't set up the hooks then, so that an XGE event from the
113 server doesn't crash our client */
114 if (dpyinfo && dpyinfo->codes)
115 {
116 /* We don't use an extension opcode, so we have to set the handlers
117 * directly. If GenericEvent would be > 64, the job would be done by
118 * XExtAddDisplay */
119 XESetWireToEvent (dpy,
120 GenericEvent35,
121 xge_extension_hooks.wire_to_event);
122 XESetEventToWire (dpy,
123 GenericEvent35,
124 xge_extension_hooks.event_to_wire);
125 }
126 }
127 return dpyinfo;
128}
129
130/*
131 * Check extension is set up and internal data fields are filled.
132 */
133static Boolint
134_xgeCheckExtInit(Display* dpy, XExtDisplayInfo* info)
135{
136 LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display
)(dpy)
;
137 if(!_xgeCheckExtension(dpy, info))
2
Taking false branch
138 {
139 goto cleanup;
140 }
141
142 if (!info->data)
3
Taking true branch
143 {
144 XGEData* data = (XGEData*)Xmalloc(sizeof(XGEData))malloc(((sizeof(XGEData)) == 0 ? 1 : (sizeof(XGEData))));
145 if (!data) {
4
Assuming 'data' is non-null
5
Taking false branch
146 goto cleanup;
147 }
148 /* get version from server */
149 data->vers =
150 _xgeGetExtensionVersion(dpy, "Generic Event Extension", info);
6
Calling '_xgeGetExtensionVersion'
9
Returning; memory was released via 3rd parameter
151 data->extensions = NULL((void*)0);
152 info->data = (XPointer)data;
10
Use of memory after it is freed
153 }
154
155 UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display
)(dpy)
;
156 return True1;
157
158cleanup:
159 UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display
)(dpy)
;
160 return False0;
161}
162
163/* Return 1 if XGE extension exists, 0 otherwise. */
164static Boolint
165_xgeCheckExtension(Display* dpy, XExtDisplayInfo* info)
166{
167 return XextHasExtension(info)((info) && ((info)->codes));
168}
169
170
171/* Retrieve XGE version number from server. */
172static XGEVersionRec*
173_xgeGetExtensionVersion(Display* dpy,
174 _Xconstconst char* name,
175 XExtDisplayInfo*info)
176{
177 xGEQueryVersionReply rep;
178 xGEQueryVersionReq *req;
179 XGEVersionRec *vers;
180
181 GetReq(GEQueryVersion, req)req = (xGEQueryVersionReq *) _XGetRequest(dpy, 0, 8);
182 req->reqType = info->codes->major_opcode;
183 req->ReqType = X_GEQueryVersion0;
184 req->majorVersion = GE_MAJOR1;
185 req->minorVersion = GE_MINOR0;
186
187 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue1))
7
Taking true branch
188 {
189 Xfree(info)free((info));
8
Within the expansion of the macro 'Xfree':
a
Memory is released
190 return NULL((void*)0);
191 }
192
193 vers = (XGEVersionRec*)Xmalloc(sizeof(XGEVersionRec))malloc(((sizeof(XGEVersionRec)) == 0 ? 1 : (sizeof(XGEVersionRec
))))
;
194 vers->major_version = rep.majorVersion;
195 vers->minor_version = rep.minorVersion;
196 return vers;
197}
198
199/*
200 * Display closing routine.
201 */
202
203static int
204_xgeDpyClose(Display* dpy, XExtCodes* codes)
205{
206 XExtDisplayInfo *info = _xgeFindDisplay(dpy);
207
208 if (info->data != NULL((void*)0)) {
209 XGEData* xge_data = (XGEData*)info->data;
210
211 if (xge_data->extensions)
212 {
213 XGEExtList current, next;
214 current = xge_data->extensions;
215 while(current)
216 {
217 next = current->next;
218 Xfree(current)free((current));
219 current = next;
220 }
221 }
222
223 XFree(xge_data->vers);
224 XFree(xge_data);
225 }
226
227 if(!XextRemoveDisplay(xge_info, dpy))
228 return 0;
229
230 if (xge_info->ndisplays == 0) {
231 XextDestroyExtension(xge_info);
232 xge_info = NULL((void*)0);
233 }
234
235 return 1;
236}
237
238/*
239 * protocol to Xlib event conversion routine.
240 */
241static Boolint
242_xgeWireToEvent(Display* dpy, XEvent* re, xEvent *event)
243{
244 int extension;
245 XGEExtList it;
246 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
247 if (!info || !info->data)
248 return False0;
249 /*
250 _xgeCheckExtInit() calls LockDisplay, leading to a SIGABRT.
251 Well, I guess we don't need the data we get in CheckExtInit anyway
252 if (!_xgeCheckExtInit(dpy, info))
253 return False;
254 */
255
256 extension = ((xGenericEvent*)event)->extension;
257
258 it = ((XGEData*)info->data)->extensions;
259 while(it)
260 {
261 if (it->extension == extension)
262 {
263 return (it->hooks->wire_to_event(dpy, re, event));
264 }
265 it = it->next;
266 }
267
268 return False0;
269}
270
271/*
272 * xlib event to protocol conversion routine.
273 */
274static Statusint
275_xgeEventToWire(Display* dpy, XEvent* re, xEvent* event)
276{
277 int extension;
278 XGEExtList it;
279 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
280 if (!info || !info->data)
281 return 1; /* error! */
282
283 extension = ((XGenericEvent*)re)->extension;
284
285 it = ((XGEData*)info->data)->extensions;
286 while(it)
287 {
288 if (it->extension == extension)
289 {
290 return (it->hooks->event_to_wire(dpy, re, event));
291 }
292 it = it->next;
293 }
294
295 return Success0;
296}
297
298/*
299 * Extensions need to register callbacks for their events.
300 */
301Boolint
302_X_HIDDEN__attribute__((visibility("hidden"))) xgeExtRegister(Display* dpy, int offset, XExtensionHooks* callbacks)
303{
304 XGEExtNode* newExt;
305 XGEData* xge_data;
306
307 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
308 if (!info)
309 return False0; /* error! */
310
311 if (!_xgeCheckExtInit(dpy, info))
312 return False0;
313
314 xge_data = (XGEData*)info->data;
315
316 newExt = (XGEExtNode*)Xmalloc(sizeof(XGEExtNode))malloc(((sizeof(XGEExtNode)) == 0 ? 1 : (sizeof(XGEExtNode)))
)
;
317 if (!newExt)
318 {
319 fprintf(stderr__stderrp, "xgeExtRegister: Failed to alloc memory.\n");
320 return False0;
321 }
322
323 newExt->extension = offset;
324 newExt->hooks = callbacks;
325 newExt->next = xge_data->extensions;
326 xge_data->extensions = newExt;
327
328 return True1;
329}
330
331/***********************************************************************/
332/* Client interfaces */
333/***********************************************************************/
334
335/* Set event_base and error_base to the matching values for XGE.
336 * Note that since XGE doesn't use any errors and events, the actual return
337 * value is of limited use.
338 */
339Boolint
340XGEQueryExtension(Display* dpy, int* event_base, int* error_base)
341{
342 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
343 if (!_xgeCheckExtInit(dpy, info))
1
Calling '_xgeCheckExtInit'
344 return False0;
345
346 *event_base = info->codes->first_event;
347 *error_base = info->codes->first_error;
348 return True1;
349}
350
351/* Get XGE version number.
352 * Doesn't actually get it from server, that should have been done beforehand
353 * already
354 */
355Boolint
356XGEQueryVersion(Display* dpy,
357 int *major_version,
358 int *minor_version)
359{
360 XExtDisplayInfo* info = _xgeFindDisplay(dpy);
361 if (!info)
362 return False0;
363
364 if (!_xgeCheckExtInit(dpy, info))
365 return False0;
366
367 *major_version = ((XGEData*)info->data)->vers->major_version;
368 *minor_version = ((XGEData*)info->data)->vers->minor_version;
369
370 return True1;
371}
372