| File: | dix/privates.c |
| Location: | line 522, column 5 |
| Description: | Potential leak of memory pointed to by 'p' |
| 1 | /* | |||
| 2 | ||||
| 3 | Copyright 1993, 1998 The Open Group | |||
| 4 | ||||
| 5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
| 6 | documentation for any purpose is hereby granted without fee, provided that | |||
| 7 | the above copyright notice appear in all copies and that both that | |||
| 8 | copyright notice and this permission notice appear in supporting | |||
| 9 | documentation. | |||
| 10 | ||||
| 11 | The above copyright notice and this permission notice shall be included | |||
| 12 | in all copies or substantial portions of the Software. | |||
| 13 | ||||
| 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| 17 | IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
| 18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
| 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
| 20 | OTHER DEALINGS IN THE SOFTWARE. | |||
| 21 | ||||
| 22 | Except as contained in this notice, the name of The Open Group shall | |||
| 23 | not be used in advertising or otherwise to promote the sale, use or | |||
| 24 | other dealings in this Software without prior written authorization | |||
| 25 | from The Open Group. | |||
| 26 | ||||
| 27 | */ | |||
| 28 | /* | |||
| 29 | * Copyright © 2010, Keith Packard | |||
| 30 | * Copyright © 2010, Jamey Sharp | |||
| 31 | * | |||
| 32 | * Permission to use, copy, modify, distribute, and sell this software and its | |||
| 33 | * documentation for any purpose is hereby granted without fee, provided that | |||
| 34 | * the above copyright notice appear in all copies and that both that copyright | |||
| 35 | * notice and this permission notice appear in supporting documentation, and | |||
| 36 | * that the name of the copyright holders not be used in advertising or | |||
| 37 | * publicity pertaining to distribution of the software without specific, | |||
| 38 | * written prior permission. The copyright holders make no representations | |||
| 39 | * about the suitability of this software for any purpose. It is provided "as | |||
| 40 | * is" without express or implied warranty. | |||
| 41 | * | |||
| 42 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
| 43 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
| 44 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
| 45 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
| 46 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| 47 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| 48 | * OF THIS SOFTWARE. | |||
| 49 | */ | |||
| 50 | ||||
| 51 | #ifdef HAVE_DIX_CONFIG_H1 | |||
| 52 | #include <dix-config.h> | |||
| 53 | #endif | |||
| 54 | ||||
| 55 | #include <stddef.h> | |||
| 56 | #include "windowstr.h" | |||
| 57 | #include "resource.h" | |||
| 58 | #include "privates.h" | |||
| 59 | #include "gcstruct.h" | |||
| 60 | #include "cursorstr.h" | |||
| 61 | #include "colormapst.h" | |||
| 62 | #include "inputstr.h" | |||
| 63 | #include "scrnintstr.h" | |||
| 64 | #include "extnsionst.h" | |||
| 65 | #include "inputstr.h" | |||
| 66 | ||||
| 67 | static DevPrivateSetRec global_keys[PRIVATE_LAST]; | |||
| 68 | ||||
| 69 | static const Bool xselinux_private[PRIVATE_LAST] = { | |||
| 70 | [PRIVATE_SCREEN] = TRUE1, | |||
| 71 | [PRIVATE_CLIENT] = TRUE1, | |||
| 72 | [PRIVATE_WINDOW] = TRUE1, | |||
| 73 | [PRIVATE_PIXMAP] = TRUE1, | |||
| 74 | [PRIVATE_GC] = TRUE1, | |||
| 75 | [PRIVATE_CURSOR] = TRUE1, | |||
| 76 | [PRIVATE_COLORMAP] = TRUE1, | |||
| 77 | [PRIVATE_DEVICE] = TRUE1, | |||
| 78 | [PRIVATE_EXTENSION] = TRUE1, | |||
| 79 | [PRIVATE_SELECTION] = TRUE1, | |||
| 80 | [PRIVATE_PROPERTY] = TRUE1, | |||
| 81 | [PRIVATE_PICTURE] = TRUE1, | |||
| 82 | [PRIVATE_GLYPHSET] = TRUE1, | |||
| 83 | }; | |||
| 84 | ||||
| 85 | static const char *key_names[PRIVATE_LAST] = { | |||
| 86 | /* XSELinux uses the same private keys for numerous objects */ | |||
| 87 | [PRIVATE_XSELINUX] = "XSELINUX", | |||
| 88 | ||||
| 89 | /* Otherwise, you get a private in just the requested structure | |||
| 90 | */ | |||
| 91 | /* These can have objects created before all of the keys are registered */ | |||
| 92 | [PRIVATE_SCREEN] = "SCREEN", | |||
| 93 | [PRIVATE_EXTENSION] = "EXTENSION", | |||
| 94 | [PRIVATE_COLORMAP] = "COLORMAP", | |||
| 95 | [PRIVATE_DEVICE] = "DEVICE", | |||
| 96 | ||||
| 97 | /* These cannot have any objects before all relevant keys are registered */ | |||
| 98 | [PRIVATE_CLIENT] = "CLIENT", | |||
| 99 | [PRIVATE_PROPERTY] = "PROPERTY", | |||
| 100 | [PRIVATE_SELECTION] = "SELECTION", | |||
| 101 | [PRIVATE_WINDOW] = "WINDOW", | |||
| 102 | [PRIVATE_PIXMAP] = "PIXMAP", | |||
| 103 | [PRIVATE_GC] = "GC", | |||
| 104 | [PRIVATE_CURSOR] = "CURSOR", | |||
| 105 | [PRIVATE_CURSOR_BITS] = "CURSOR_BITS", | |||
| 106 | ||||
| 107 | /* extension privates */ | |||
| 108 | [PRIVATE_DAMAGE] = "DAMAGE", | |||
| 109 | [PRIVATE_GLYPH] = "GLYPH", | |||
| 110 | [PRIVATE_GLYPHSET] = "GLYPHSET", | |||
| 111 | [PRIVATE_PICTURE] = "PICTURE", | |||
| 112 | [PRIVATE_SYNC_FENCE] = "SYNC_FENCE", | |||
| 113 | }; | |||
| 114 | ||||
| 115 | static const Bool screen_specific_private[PRIVATE_LAST] = { | |||
| 116 | [PRIVATE_SCREEN] = FALSE0, | |||
| 117 | [PRIVATE_CLIENT] = FALSE0, | |||
| 118 | [PRIVATE_WINDOW] = TRUE1, | |||
| 119 | [PRIVATE_PIXMAP] = TRUE1, | |||
| 120 | [PRIVATE_GC] = TRUE1, | |||
| 121 | [PRIVATE_CURSOR] = FALSE0, | |||
| 122 | [PRIVATE_COLORMAP] = FALSE0, | |||
| 123 | [PRIVATE_DEVICE] = FALSE0, | |||
| 124 | [PRIVATE_EXTENSION] = FALSE0, | |||
| 125 | [PRIVATE_SELECTION] = FALSE0, | |||
| 126 | [PRIVATE_PROPERTY] = FALSE0, | |||
| 127 | [PRIVATE_PICTURE] = TRUE1, | |||
| 128 | [PRIVATE_GLYPHSET] = FALSE0, | |||
| 129 | }; | |||
| 130 | ||||
| 131 | typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes); | |||
| 132 | ||||
| 133 | typedef enum { FixupMove, FixupRealloc } FixupType; | |||
| 134 | ||||
| 135 | static Bool | |||
| 136 | dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes) | |||
| 137 | { | |||
| 138 | void *new_privates; | |||
| 139 | ||||
| 140 | new_privates = realloc(*privates, old_offset + bytes); | |||
| 141 | if (!new_privates) | |||
| 142 | return FALSE0; | |||
| 143 | memset((char *) new_privates + old_offset, '\0', bytes)__builtin___memset_chk ((char *) new_privates + old_offset, '\0' , bytes, __builtin_object_size ((char *) new_privates + old_offset , 0)); | |||
| 144 | *privates = new_privates; | |||
| 145 | return TRUE1; | |||
| 146 | } | |||
| 147 | ||||
| 148 | static Bool | |||
| 149 | dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes) | |||
| 150 | { | |||
| 151 | memmove((char *) *privates + bytes, *privates, new_offset - bytes)__builtin___memmove_chk ((char *) *privates + bytes, *privates , new_offset - bytes, __builtin_object_size ((char *) *privates + bytes, 0)); | |||
| 152 | memset(*privates, '\0', bytes)__builtin___memset_chk (*privates, '\0', bytes, __builtin_object_size (*privates, 0)); | |||
| 153 | return TRUE1; | |||
| 154 | } | |||
| 155 | ||||
| 156 | static Bool | |||
| 157 | fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes) | |||
| 158 | { | |||
| 159 | intptr_t dist; | |||
| 160 | char *old; | |||
| 161 | char *new; | |||
| 162 | DevPrivateKey *keyp, key; | |||
| 163 | DevPrivateType type; | |||
| 164 | int size; | |||
| 165 | ||||
| 166 | old = (char *) pScreen->devPrivates; | |||
| 167 | size = global_keys[PRIVATE_SCREEN].offset; | |||
| 168 | if (!fixup (&pScreen->devPrivates, size, bytes)) | |||
| 169 | return FALSE0; | |||
| 170 | ||||
| 171 | /* Screen privates can contain screen-specific private keys | |||
| 172 | * for other types. When they move, the linked list we use to | |||
| 173 | * track them gets scrambled. Fix that by computing the change | |||
| 174 | * in the location of each private adjusting our linked list | |||
| 175 | * pointers to match | |||
| 176 | */ | |||
| 177 | ||||
| 178 | new = (char *) pScreen->devPrivates; | |||
| 179 | ||||
| 180 | /* Moving means everyone shifts up in the privates by 'bytes' amount, | |||
| 181 | * realloc means the base pointer moves | |||
| 182 | */ | |||
| 183 | if (fixup == dixMovePrivates) | |||
| 184 | new += bytes; | |||
| 185 | ||||
| 186 | dist = new - old; | |||
| 187 | ||||
| 188 | if (dist) { | |||
| 189 | for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++) | |||
| 190 | ||||
| 191 | /* Walk the privates list, being careful as the | |||
| 192 | * pointers are scrambled before we patch them. | |||
| 193 | */ | |||
| 194 | for (keyp = &pScreen->screenSpecificPrivates[type].key; | |||
| 195 | (key = *keyp) != NULL((void*)0); | |||
| 196 | keyp = &key->next) | |||
| 197 | { | |||
| 198 | ||||
| 199 | /* Only mangle things if the private structure | |||
| 200 | * is contained within the allocation. Privates | |||
| 201 | * stored elsewhere will be left alone | |||
| 202 | */ | |||
| 203 | if (old <= (char *) key && (char *) key < old + size) | |||
| 204 | { | |||
| 205 | /* Compute new location of key */ | |||
| 206 | key = (DevPrivateKey) ((char *) key + dist); | |||
| 207 | ||||
| 208 | /* Patch the list */ | |||
| 209 | *keyp = key; | |||
| 210 | } | |||
| 211 | } | |||
| 212 | } | |||
| 213 | return TRUE1; | |||
| 214 | } | |||
| 215 | ||||
| 216 | static Bool | |||
| 217 | fixupScreens(FixupFunc fixup, unsigned bytes) | |||
| 218 | { | |||
| 219 | int s; | |||
| 220 | ||||
| 221 | for (s = 0; s < screenInfo.numScreens; s++) | |||
| 222 | if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes)) | |||
| 223 | return FALSE0; | |||
| 224 | ||||
| 225 | for (s = 0; s < screenInfo.numGPUScreens; s++) | |||
| 226 | if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes)) | |||
| 227 | return FALSE0; | |||
| 228 | return TRUE1; | |||
| 229 | } | |||
| 230 | ||||
| 231 | static Bool | |||
| 232 | fixupServerClient(FixupFunc fixup, unsigned bytes) | |||
| 233 | { | |||
| 234 | if (serverClient) | |||
| 235 | return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset, | |||
| 236 | bytes); | |||
| 237 | return TRUE1; | |||
| 238 | } | |||
| 239 | ||||
| 240 | static Bool | |||
| 241 | fixupExtensions(FixupFunc fixup, unsigned bytes) | |||
| 242 | { | |||
| 243 | unsigned char major; | |||
| 244 | ExtensionEntry *extension; | |||
| 245 | ||||
| 246 | for (major = EXTENSION_BASE128; (extension = GetExtensionEntry(major)); | |||
| 247 | major++) | |||
| 248 | if (!fixup | |||
| 249 | (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes)) | |||
| 250 | return FALSE0; | |||
| 251 | return TRUE1; | |||
| 252 | } | |||
| 253 | ||||
| 254 | static Bool | |||
| 255 | fixupDefaultColormaps(FixupFunc fixup, unsigned bytes) | |||
| 256 | { | |||
| 257 | int s; | |||
| 258 | ||||
| 259 | for (s = 0; s < screenInfo.numScreens; s++) { | |||
| 260 | ColormapPtr cmap; | |||
| 261 | ||||
| 262 | dixLookupResourceByType((void **) &cmap, | |||
| 263 | screenInfo.screens[s]->defColormap, RT_COLORMAP((RESTYPE)6), | |||
| 264 | serverClient, DixCreateAccess(1<<3)); | |||
| 265 | if (cmap && | |||
| 266 | !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes)) | |||
| 267 | return FALSE0; | |||
| 268 | } | |||
| 269 | return TRUE1; | |||
| 270 | } | |||
| 271 | ||||
| 272 | static Bool | |||
| 273 | fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes) | |||
| 274 | { | |||
| 275 | while (device) { | |||
| 276 | if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes)) | |||
| 277 | return FALSE0; | |||
| 278 | device = device->next; | |||
| 279 | } | |||
| 280 | return TRUE1; | |||
| 281 | } | |||
| 282 | ||||
| 283 | static Bool | |||
| 284 | fixupDevices(FixupFunc fixup, unsigned bytes) | |||
| 285 | { | |||
| 286 | return (fixupDeviceList(inputInfo.devices, fixup, bytes) && | |||
| 287 | fixupDeviceList(inputInfo.off_devices, fixup, bytes)); | |||
| 288 | } | |||
| 289 | ||||
| 290 | static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = { | |||
| 291 | [PRIVATE_SCREEN] = fixupScreens, | |||
| 292 | [PRIVATE_CLIENT] = fixupServerClient, | |||
| 293 | [PRIVATE_EXTENSION] = fixupExtensions, | |||
| 294 | [PRIVATE_COLORMAP] = fixupDefaultColormaps, | |||
| 295 | [PRIVATE_DEVICE] = fixupDevices, | |||
| 296 | }; | |||
| 297 | ||||
| 298 | static void | |||
| 299 | grow_private_set(DevPrivateSetPtr set, unsigned bytes) | |||
| 300 | { | |||
| 301 | DevPrivateKey k; | |||
| 302 | ||||
| 303 | for (k = set->key; k; k = k->next) | |||
| 304 | k->offset += bytes; | |||
| 305 | set->offset += bytes; | |||
| 306 | } | |||
| 307 | ||||
| 308 | static void | |||
| 309 | grow_screen_specific_set(DevPrivateType type, unsigned bytes) | |||
| 310 | { | |||
| 311 | int s; | |||
| 312 | ||||
| 313 | /* Update offsets for all screen-specific keys */ | |||
| 314 | for (s = 0; s < screenInfo.numScreens; s++) { | |||
| 315 | ScreenPtr pScreen = screenInfo.screens[s]; | |||
| 316 | ||||
| 317 | grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); | |||
| 318 | } | |||
| 319 | for (s = 0; s < screenInfo.numGPUScreens; s++) { | |||
| 320 | ScreenPtr pScreen = screenInfo.gpuscreens[s]; | |||
| 321 | ||||
| 322 | grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); | |||
| 323 | } | |||
| 324 | } | |||
| 325 | ||||
| 326 | /* | |||
| 327 | * Register a private key. This takes the type of object the key will | |||
| 328 | * be used with, which may be PRIVATE_ALL indicating that this key | |||
| 329 | * will be used with all of the private objects. If 'size' is | |||
| 330 | * non-zero, then the specified amount of space will be allocated in | |||
| 331 | * the private storage. Otherwise, space for a single pointer will | |||
| 332 | * be allocated which can be set with dixSetPrivate | |||
| 333 | */ | |||
| 334 | Bool | |||
| 335 | dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) | |||
| 336 | { | |||
| 337 | DevPrivateType t; | |||
| 338 | int offset; | |||
| 339 | unsigned bytes; | |||
| 340 | ||||
| 341 | if (key->initialized) { | |||
| 342 | assert(size == key->size)(__builtin_expect(!(size == key->size), 0) ? __assert_rtn( __func__, "privates.c", 342, "size == key->size") : (void) 0); | |||
| 343 | return TRUE1; | |||
| 344 | } | |||
| 345 | ||||
| 346 | /* Compute required space */ | |||
| 347 | bytes = size; | |||
| 348 | if (size == 0) | |||
| 349 | bytes = sizeof(void *); | |||
| 350 | ||||
| 351 | /* align to pointer size */ | |||
| 352 | bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); | |||
| 353 | ||||
| 354 | /* Update offsets for all affected keys */ | |||
| 355 | if (type == PRIVATE_XSELINUX) { | |||
| 356 | ||||
| 357 | /* Resize if we can, or make sure nothing's allocated if we can't | |||
| 358 | */ | |||
| 359 | for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) | |||
| 360 | if (xselinux_private[t]) { | |||
| 361 | if (!allocated_early[t]) | |||
| 362 | assert(!global_keys[t].created)(__builtin_expect(!(!global_keys[t].created), 0) ? __assert_rtn (__func__, "privates.c", 362, "!global_keys[t].created") : (void )0); | |||
| 363 | else if (!allocated_early[t] (dixReallocPrivates, bytes)) | |||
| 364 | return FALSE0; | |||
| 365 | } | |||
| 366 | ||||
| 367 | /* Move all existing keys up in the privates space to make | |||
| 368 | * room for this new global key | |||
| 369 | */ | |||
| 370 | for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { | |||
| 371 | if (xselinux_private[t]) { | |||
| 372 | grow_private_set(&global_keys[t], bytes); | |||
| 373 | grow_screen_specific_set(t, bytes); | |||
| 374 | if (allocated_early[t]) | |||
| 375 | allocated_early[t] (dixMovePrivates, bytes); | |||
| 376 | } | |||
| 377 | ||||
| 378 | } | |||
| 379 | ||||
| 380 | offset = 0; | |||
| 381 | } | |||
| 382 | else { | |||
| 383 | /* Resize if we can, or make sure nothing's allocated if we can't */ | |||
| 384 | if (!allocated_early[type]) | |||
| 385 | assert(!global_keys[type].created)(__builtin_expect(!(!global_keys[type].created), 0) ? __assert_rtn (__func__, "privates.c", 385, "!global_keys[type].created") : (void)0); | |||
| 386 | else if (!allocated_early[type] (dixReallocPrivates, bytes)) | |||
| 387 | return FALSE0; | |||
| 388 | offset = global_keys[type].offset; | |||
| 389 | global_keys[type].offset += bytes; | |||
| 390 | grow_screen_specific_set(type, bytes); | |||
| 391 | } | |||
| 392 | ||||
| 393 | /* Setup this key */ | |||
| 394 | key->offset = offset; | |||
| 395 | key->size = size; | |||
| 396 | key->initialized = TRUE1; | |||
| 397 | key->type = type; | |||
| 398 | key->allocated = FALSE0; | |||
| 399 | key->next = global_keys[type].key; | |||
| 400 | global_keys[type].key = key; | |||
| 401 | ||||
| 402 | return TRUE1; | |||
| 403 | } | |||
| 404 | ||||
| 405 | Bool | |||
| 406 | dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen, | |||
| 407 | DevPrivateType type, unsigned size) | |||
| 408 | { | |||
| 409 | DevPrivateKey key; | |||
| 410 | ||||
| 411 | if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0)) | |||
| 412 | return FALSE0; | |||
| 413 | key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey); | |||
| 414 | if (key != NULL((void*)0)) { | |||
| 415 | assert(key->size == size)(__builtin_expect(!(key->size == size), 0) ? __assert_rtn( __func__, "privates.c", 415, "key->size == size") : (void) 0); | |||
| 416 | assert(key->type == type)(__builtin_expect(!(key->type == type), 0) ? __assert_rtn( __func__, "privates.c", 416, "key->type == type") : (void) 0); | |||
| 417 | return TRUE1; | |||
| 418 | } | |||
| 419 | key = calloc(sizeof(DevPrivateKeyRec), 1); | |||
| 420 | if (!key) | |||
| 421 | return FALSE0; | |||
| 422 | if (!dixRegisterPrivateKey(key, type, size)) { | |||
| 423 | free(key); | |||
| 424 | return FALSE0; | |||
| 425 | } | |||
| 426 | key->allocated = TRUE1; | |||
| 427 | dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key); | |||
| 428 | return TRUE1; | |||
| 429 | } | |||
| 430 | ||||
| 431 | DevPrivateKey | |||
| 432 | _dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen) | |||
| 433 | { | |||
| 434 | return dixGetPrivate(&pScreen->devPrivates, &key->screenKey); | |||
| 435 | } | |||
| 436 | ||||
| 437 | /* | |||
| 438 | * Initialize privates by zeroing them | |||
| 439 | */ | |||
| 440 | void | |||
| 441 | _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) | |||
| 442 | { | |||
| 443 | assert (!screen_specific_private[type])(__builtin_expect(!(!screen_specific_private[type]), 0) ? __assert_rtn (__func__, "privates.c", 443, "!screen_specific_private[type]" ) : (void)0); | |||
| 444 | ||||
| 445 | global_keys[type].created++; | |||
| 446 | if (xselinux_private[type]) | |||
| 447 | global_keys[PRIVATE_XSELINUX].created++; | |||
| 448 | if (global_keys[type].offset == 0) | |||
| 449 | addr = 0; | |||
| 450 | *privates = addr; | |||
| 451 | memset(addr, '\0', global_keys[type].offset)__builtin___memset_chk (addr, '\0', global_keys[type].offset, __builtin_object_size (addr, 0)); | |||
| 452 | } | |||
| 453 | ||||
| 454 | /* | |||
| 455 | * Clean up privates | |||
| 456 | */ | |||
| 457 | void | |||
| 458 | _dixFiniPrivates(PrivatePtr privates, DevPrivateType type) | |||
| 459 | { | |||
| 460 | global_keys[type].created--; | |||
| 461 | if (xselinux_private[type]) | |||
| 462 | global_keys[PRIVATE_XSELINUX].created--; | |||
| 463 | } | |||
| 464 | ||||
| 465 | /* | |||
| 466 | * Allocate new object with privates. | |||
| 467 | * | |||
| 468 | * This is expected to be invoked from the | |||
| 469 | * dixAllocateObjectWithPrivates macro | |||
| 470 | */ | |||
| 471 | void * | |||
| 472 | _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, | |||
| 473 | unsigned offset, DevPrivateType type) | |||
| 474 | { | |||
| 475 | unsigned totalSize; | |||
| 476 | void *object; | |||
| 477 | PrivatePtr privates; | |||
| 478 | PrivatePtr *devPrivates; | |||
| 479 | ||||
| 480 | assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST)(__builtin_expect(!(type > PRIVATE_SCREEN && type < PRIVATE_LAST), 0) ? __assert_rtn(__func__, "privates.c", 480 , "type > PRIVATE_SCREEN && type < PRIVATE_LAST" ) : (void)0); | |||
| 481 | assert(!screen_specific_private[type])(__builtin_expect(!(!screen_specific_private[type]), 0) ? __assert_rtn (__func__, "privates.c", 481, "!screen_specific_private[type]" ) : (void)0); | |||
| 482 | ||||
| 483 | /* round up so that void * is aligned */ | |||
| 484 | baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); | |||
| 485 | totalSize = baseSize + global_keys[type].offset; | |||
| 486 | object = malloc(totalSize); | |||
| 487 | if (!object) | |||
| 488 | return NULL((void*)0); | |||
| 489 | ||||
| 490 | memset(object, '\0', clear)__builtin___memset_chk (object, '\0', clear, __builtin_object_size (object, 0)); | |||
| 491 | privates = (PrivatePtr) (((char *) object) + baseSize); | |||
| 492 | devPrivates = (PrivatePtr *) ((char *) object + offset); | |||
| 493 | ||||
| 494 | _dixInitPrivates(devPrivates, privates, type); | |||
| 495 | ||||
| 496 | return object; | |||
| 497 | } | |||
| 498 | ||||
| 499 | /* | |||
| 500 | * Allocate privates separately from containing object. | |||
| 501 | * Used for clients and screens. | |||
| 502 | */ | |||
| 503 | Bool | |||
| 504 | dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) | |||
| 505 | { | |||
| 506 | unsigned size; | |||
| 507 | PrivatePtr p; | |||
| 508 | ||||
| 509 | assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST)(__builtin_expect(!(type > PRIVATE_XSELINUX && type < PRIVATE_LAST), 0) ? __assert_rtn(__func__, "privates.c" , 509, "type > PRIVATE_XSELINUX && type < PRIVATE_LAST" ) : (void)0); | |||
| 510 | assert(!screen_specific_private[type])(__builtin_expect(!(!screen_specific_private[type]), 0) ? __assert_rtn (__func__, "privates.c", 510, "!screen_specific_private[type]" ) : (void)0); | |||
| 511 | ||||
| 512 | size = global_keys[type].offset; | |||
| 513 | if (!size) { | |||
| ||||
| 514 | p = NULL((void*)0); | |||
| 515 | } | |||
| 516 | else { | |||
| 517 | if (!(p = malloc(size))) | |||
| 518 | return FALSE0; | |||
| 519 | } | |||
| 520 | ||||
| 521 | _dixInitPrivates(privates, p, type); | |||
| 522 | ++global_keys[type].allocated; | |||
| ||||
| 523 | ||||
| 524 | return TRUE1; | |||
| 525 | } | |||
| 526 | ||||
| 527 | /* | |||
| 528 | * Free an object that has privates | |||
| 529 | * | |||
| 530 | * This is expected to be invoked from the | |||
| 531 | * dixFreeObjectWithPrivates macro | |||
| 532 | */ | |||
| 533 | void | |||
| 534 | _dixFreeObjectWithPrivates(void *object, PrivatePtr privates, | |||
| 535 | DevPrivateType type) | |||
| 536 | { | |||
| 537 | _dixFiniPrivates(privates, type); | |||
| 538 | free(object); | |||
| 539 | } | |||
| 540 | ||||
| 541 | /* | |||
| 542 | * Called to free screen or client privates | |||
| 543 | */ | |||
| 544 | void | |||
| 545 | dixFreePrivates(PrivatePtr privates, DevPrivateType type) | |||
| 546 | { | |||
| 547 | _dixFiniPrivates(privates, type); | |||
| 548 | --global_keys[type].allocated; | |||
| 549 | free(privates); | |||
| 550 | } | |||
| 551 | ||||
| 552 | /* | |||
| 553 | * Return size of privates for the specified type | |||
| 554 | */ | |||
| 555 | extern _X_EXPORT__attribute__((visibility("default"))) int | |||
| 556 | dixPrivatesSize(DevPrivateType type) | |||
| 557 | { | |||
| 558 | assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST)(__builtin_expect(!(type >= PRIVATE_SCREEN && type < PRIVATE_LAST), 0) ? __assert_rtn(__func__, "privates.c" , 558, "type >= PRIVATE_SCREEN && type < PRIVATE_LAST" ) : (void)0); | |||
| 559 | assert (!screen_specific_private[type])(__builtin_expect(!(!screen_specific_private[type]), 0) ? __assert_rtn (__func__, "privates.c", 559, "!screen_specific_private[type]" ) : (void)0); | |||
| 560 | ||||
| 561 | return global_keys[type].offset; | |||
| 562 | } | |||
| 563 | ||||
| 564 | /* Table of devPrivates offsets */ | |||
| 565 | static const int offsets[] = { | |||
| 566 | -1, /* RT_NONE */ | |||
| 567 | offsetof(WindowRec, devPrivates)__builtin_offsetof(WindowRec, devPrivates), /* RT_WINDOW */ | |||
| 568 | offsetof(PixmapRec, devPrivates)__builtin_offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */ | |||
| 569 | offsetof(GC, devPrivates)__builtin_offsetof(GC, devPrivates), /* RT_GC */ | |||
| 570 | -1, /* RT_FONT */ | |||
| 571 | offsetof(CursorRec, devPrivates)__builtin_offsetof(CursorRec, devPrivates), /* RT_CURSOR */ | |||
| 572 | offsetof(ColormapRec, devPrivates)__builtin_offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */ | |||
| 573 | }; | |||
| 574 | ||||
| 575 | #define NUM_OFFSETS(sizeof (offsets) / sizeof (offsets[0])) (sizeof (offsets) / sizeof (offsets[0])) | |||
| 576 | ||||
| 577 | int | |||
| 578 | dixLookupPrivateOffset(RESTYPE type) | |||
| 579 | { | |||
| 580 | /* | |||
| 581 | * Special kludge for DBE which registers a new resource type that | |||
| 582 | * points at pixmaps (thanks, DBE) | |||
| 583 | */ | |||
| 584 | if (type & RC_DRAWABLE((RESTYPE)1<<30)) { | |||
| 585 | if (type == RT_WINDOW((RESTYPE)1|((RESTYPE)1<<30))) | |||
| 586 | return offsets[RT_WINDOW((RESTYPE)1|((RESTYPE)1<<30)) & TypeMask]; | |||
| 587 | else | |||
| 588 | return offsets[RT_PIXMAP((RESTYPE)2|((RESTYPE)1<<30)) & TypeMask]; | |||
| 589 | } | |||
| 590 | type = type & TypeMask; | |||
| 591 | if (type < NUM_OFFSETS(sizeof (offsets) / sizeof (offsets[0]))) | |||
| 592 | return offsets[type]; | |||
| 593 | return -1; | |||
| 594 | } | |||
| 595 | ||||
| 596 | /* | |||
| 597 | * Screen-specific privates | |||
| 598 | */ | |||
| 599 | ||||
| 600 | extern _X_EXPORT__attribute__((visibility("default"))) Bool | |||
| 601 | dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, | |||
| 602 | DevPrivateType type, unsigned size) | |||
| 603 | { | |||
| 604 | int offset; | |||
| 605 | unsigned bytes; | |||
| 606 | ||||
| 607 | if (!screen_specific_private[type]) | |||
| 608 | FatalError("Attempt to allocate screen-specific private storage for type %s\n", | |||
| 609 | key_names[type]); | |||
| 610 | ||||
| 611 | if (key->initialized) { | |||
| 612 | assert(size == key->size)(__builtin_expect(!(size == key->size), 0) ? __assert_rtn( __func__, "privates.c", 612, "size == key->size") : (void) 0); | |||
| 613 | return TRUE1; | |||
| 614 | } | |||
| 615 | ||||
| 616 | /* Compute required space */ | |||
| 617 | bytes = size; | |||
| 618 | if (size == 0) | |||
| 619 | bytes = sizeof(void *); | |||
| 620 | ||||
| 621 | /* align to void * size */ | |||
| 622 | bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); | |||
| 623 | ||||
| 624 | assert (!allocated_early[type])(__builtin_expect(!(!allocated_early[type]), 0) ? __assert_rtn (__func__, "privates.c", 624, "!allocated_early[type]") : (void )0); | |||
| 625 | assert (!pScreen->screenSpecificPrivates[type].created)(__builtin_expect(!(!pScreen->screenSpecificPrivates[type] .created), 0) ? __assert_rtn(__func__, "privates.c", 625, "!pScreen->screenSpecificPrivates[type].created" ) : (void)0); | |||
| 626 | offset = pScreen->screenSpecificPrivates[type].offset; | |||
| 627 | pScreen->screenSpecificPrivates[type].offset += bytes; | |||
| 628 | ||||
| 629 | /* Setup this key */ | |||
| 630 | key->offset = offset; | |||
| 631 | key->size = size; | |||
| 632 | key->initialized = TRUE1; | |||
| 633 | key->type = type; | |||
| 634 | key->allocated = FALSE0; | |||
| 635 | key->next = pScreen->screenSpecificPrivates[type].key; | |||
| 636 | pScreen->screenSpecificPrivates[type].key = key; | |||
| 637 | ||||
| 638 | return TRUE1; | |||
| 639 | } | |||
| 640 | ||||
| 641 | /* Clean up screen-specific privates before CloseScreen */ | |||
| 642 | void | |||
| 643 | dixFreeScreenSpecificPrivates(ScreenPtr pScreen) | |||
| 644 | { | |||
| 645 | DevPrivateType t; | |||
| 646 | ||||
| 647 | for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { | |||
| 648 | DevPrivateKey key; | |||
| 649 | ||||
| 650 | for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) { | |||
| 651 | key->initialized = FALSE0; | |||
| 652 | } | |||
| 653 | } | |||
| 654 | } | |||
| 655 | ||||
| 656 | /* Initialize screen-specific privates in AddScreen */ | |||
| 657 | void | |||
| 658 | dixInitScreenSpecificPrivates(ScreenPtr pScreen) | |||
| 659 | { | |||
| 660 | DevPrivateType t; | |||
| 661 | ||||
| 662 | for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) | |||
| 663 | pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset; | |||
| 664 | } | |||
| 665 | ||||
| 666 | /* Initialize screen-specific privates in AddScreen */ | |||
| 667 | void | |||
| 668 | _dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type) | |||
| 669 | { | |||
| 670 | int privates_size; | |||
| 671 | assert (screen_specific_private[type])(__builtin_expect(!(screen_specific_private[type]), 0) ? __assert_rtn (__func__, "privates.c", 671, "screen_specific_private[type]" ) : (void)0); | |||
| 672 | ||||
| 673 | if (pScreen) { | |||
| 674 | privates_size = pScreen->screenSpecificPrivates[type].offset; | |||
| 675 | pScreen->screenSpecificPrivates[type].created++; | |||
| 676 | } | |||
| 677 | else | |||
| 678 | privates_size = global_keys[type].offset; | |||
| 679 | ||||
| 680 | global_keys[type].created++; | |||
| 681 | if (xselinux_private[type]) | |||
| 682 | global_keys[PRIVATE_XSELINUX].created++; | |||
| 683 | if (privates_size == 0) | |||
| 684 | addr = 0; | |||
| 685 | *privates = addr; | |||
| 686 | memset(addr, '\0', privates_size)__builtin___memset_chk (addr, '\0', privates_size, __builtin_object_size (addr, 0)); | |||
| 687 | } | |||
| 688 | ||||
| 689 | void * | |||
| 690 | _dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen, | |||
| 691 | unsigned baseSize, | |||
| 692 | unsigned clear, | |||
| 693 | unsigned offset, | |||
| 694 | DevPrivateType type) | |||
| 695 | { | |||
| 696 | unsigned totalSize; | |||
| 697 | void *object; | |||
| 698 | PrivatePtr privates; | |||
| 699 | PrivatePtr *devPrivates; | |||
| 700 | int privates_size; | |||
| 701 | ||||
| 702 | assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST)(__builtin_expect(!(type > PRIVATE_SCREEN && type < PRIVATE_LAST), 0) ? __assert_rtn(__func__, "privates.c", 702 , "type > PRIVATE_SCREEN && type < PRIVATE_LAST" ) : (void)0); | |||
| 703 | assert (screen_specific_private[type])(__builtin_expect(!(screen_specific_private[type]), 0) ? __assert_rtn (__func__, "privates.c", 703, "screen_specific_private[type]" ) : (void)0); | |||
| 704 | ||||
| 705 | if (pScreen) | |||
| 706 | privates_size = pScreen->screenSpecificPrivates[type].offset; | |||
| 707 | else | |||
| 708 | privates_size = global_keys[type].offset; | |||
| 709 | /* round up so that pointer is aligned */ | |||
| 710 | baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); | |||
| 711 | totalSize = baseSize + privates_size; | |||
| 712 | object = malloc(totalSize); | |||
| 713 | if (!object) | |||
| 714 | return NULL((void*)0); | |||
| 715 | ||||
| 716 | memset(object, '\0', clear)__builtin___memset_chk (object, '\0', clear, __builtin_object_size (object, 0)); | |||
| 717 | privates = (PrivatePtr) (((char *) object) + baseSize); | |||
| 718 | devPrivates = (PrivatePtr *) ((char *) object + offset); | |||
| 719 | ||||
| 720 | _dixInitScreenPrivates(pScreen, devPrivates, privates, type); | |||
| 721 | ||||
| 722 | return object; | |||
| 723 | } | |||
| 724 | ||||
| 725 | int | |||
| 726 | dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type) | |||
| 727 | { | |||
| 728 | assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST)(__builtin_expect(!(type >= PRIVATE_SCREEN && type < PRIVATE_LAST), 0) ? __assert_rtn(__func__, "privates.c" , 728, "type >= PRIVATE_SCREEN && type < PRIVATE_LAST" ) : (void)0); | |||
| 729 | ||||
| 730 | if (screen_specific_private[type]) | |||
| 731 | return pScreen->screenSpecificPrivates[type].offset; | |||
| 732 | else | |||
| 733 | return global_keys[type].offset; | |||
| 734 | } | |||
| 735 | ||||
| 736 | void | |||
| 737 | dixPrivateUsage(void) | |||
| 738 | { | |||
| 739 | int objects = 0; | |||
| 740 | int bytes = 0; | |||
| 741 | int alloc = 0; | |||
| 742 | DevPrivateType t; | |||
| 743 | ||||
| 744 | for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) { | |||
| 745 | if (global_keys[t].offset) { | |||
| 746 | ErrorF | |||
| 747 | ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n", | |||
| 748 | key_names[t], global_keys[t].created, global_keys[t].offset, | |||
| 749 | global_keys[t].created * global_keys[t].offset, global_keys[t].allocated); | |||
| 750 | bytes += global_keys[t].created * global_keys[t].offset; | |||
| 751 | objects += global_keys[t].created; | |||
| 752 | alloc += global_keys[t].allocated; | |||
| 753 | } | |||
| 754 | } | |||
| 755 | ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc); | |||
| 756 | } | |||
| 757 | ||||
| 758 | void | |||
| 759 | dixResetPrivates(void) | |||
| 760 | { | |||
| 761 | DevPrivateType t; | |||
| 762 | ||||
| 763 | for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { | |||
| 764 | DevPrivateKey key, next; | |||
| 765 | ||||
| 766 | for (key = global_keys[t].key; key; key = next) { | |||
| 767 | next = key->next; | |||
| 768 | key->offset = 0; | |||
| 769 | key->initialized = FALSE0; | |||
| 770 | key->size = 0; | |||
| 771 | key->type = 0; | |||
| 772 | if (key->allocated) | |||
| 773 | free(key); | |||
| 774 | } | |||
| 775 | if (global_keys[t].created) { | |||
| 776 | ErrorF("%d %ss still allocated at reset\n", | |||
| 777 | global_keys[t].created, key_names[t]); | |||
| 778 | dixPrivateUsage(); | |||
| 779 | } | |||
| 780 | global_keys[t].key = NULL((void*)0); | |||
| 781 | global_keys[t].offset = 0; | |||
| 782 | global_keys[t].created = 0; | |||
| 783 | global_keys[t].allocated = 0; | |||
| 784 | } | |||
| 785 | } |