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 | } |