| File: | Xge.c |
| Location: | line 152, column 20 |
| Description: | Use of memory after it is freed |
| 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 | ||||
| 46 | typedef struct { | |||
| 47 | int present; | |||
| 48 | short major_version; | |||
| 49 | short minor_version; | |||
| 50 | } XGEVersionRec; | |||
| 51 | ||||
| 52 | /* NULL terminated list of registered extensions. */ | |||
| 53 | typedef struct _XGEExtNode { | |||
| 54 | int extension; | |||
| 55 | XExtensionHooks* hooks; | |||
| 56 | struct _XGEExtNode* next; | |||
| 57 | } XGEExtNode, *XGEExtList; | |||
| 58 | ||||
| 59 | /* Internal data for GE extension */ | |||
| 60 | typedef struct _XGEData { | |||
| 61 | XEvent data; | |||
| 62 | XGEVersionRec *vers; | |||
| 63 | XGEExtList extensions; | |||
| 64 | } XGEData; | |||
| 65 | ||||
| 66 | ||||
| 67 | /* forward declarations */ | |||
| 68 | static XExtDisplayInfo* _xgeFindDisplay(Display*); | |||
| 69 | static Boolint _xgeWireToEvent(Display*, XEvent*, xEvent*); | |||
| 70 | static Statusint _xgeEventToWire(Display*, XEvent*, xEvent*); | |||
| 71 | static int _xgeDpyClose(Display*, XExtCodes*); | |||
| 72 | static XGEVersionRec* _xgeGetExtensionVersion(Display*, | |||
| 73 | _Xconstconst char*, | |||
| 74 | XExtDisplayInfo*); | |||
| 75 | static Boolint _xgeCheckExtension(Display* dpy, XExtDisplayInfo* info); | |||
| 76 | ||||
| 77 | /* main extension information data */ | |||
| 78 | static XExtensionInfo *xge_info; | |||
| 79 | static const char xge_extension_name[] = GE_NAME"Generic Event Extension"; | |||
| 80 | static 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 | ||||
| 95 | static 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 | */ | |||
| 133 | static 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)) | |||
| 138 | { | |||
| 139 | goto cleanup; | |||
| 140 | } | |||
| 141 | ||||
| 142 | if (!info->data) | |||
| 143 | { | |||
| 144 | XGEData* data = (XGEData*)Xmalloc(sizeof(XGEData))malloc(((sizeof(XGEData)) == 0 ? 1 : (sizeof(XGEData)))); | |||
| 145 | if (!data) { | |||
| 146 | goto cleanup; | |||
| 147 | } | |||
| 148 | /* get version from server */ | |||
| 149 | data->vers = | |||
| 150 | _xgeGetExtensionVersion(dpy, "Generic Event Extension", info); | |||
| 151 | data->extensions = NULL((void*)0); | |||
| 152 | info->data = (XPointer)data; | |||
| ||||
| 153 | } | |||
| 154 | ||||
| 155 | UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(dpy); | |||
| 156 | return True1; | |||
| 157 | ||||
| 158 | cleanup: | |||
| 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. */ | |||
| 164 | static 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. */ | |||
| 172 | static 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)) | |||
| 188 | { | |||
| 189 | Xfree(info)free((info)); | |||
| 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 | ||||
| 203 | static 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 | */ | |||
| 241 | static 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 | */ | |||
| 274 | static 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 | */ | |||
| 301 | Boolint | |||
| 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 | */ | |||
| 339 | Boolint | |||
| 340 | XGEQueryExtension(Display* dpy, int* event_base, int* error_base) | |||
| 341 | { | |||
| 342 | XExtDisplayInfo* info = _xgeFindDisplay(dpy); | |||
| 343 | if (!_xgeCheckExtInit(dpy, info)) | |||
| ||||
| 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 | */ | |||
| 355 | Boolint | |||
| 356 | XGEQueryVersion(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 |