Bug Summary

File:dix/privates.c
Location:line 522, column 5
Description:Potential leak of memory pointed to by 'p'

Annotated Source Code

1/*
2
3Copyright 1993, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from 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
67static DevPrivateSetRec global_keys[PRIVATE_LAST];
68
69static 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
85static 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
115static 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
131typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes);
132
133typedef enum { FixupMove, FixupRealloc } FixupType;
134
135static Bool
136dixReallocPrivates(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
148static Bool
149dixMovePrivates(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
156static Bool
157fixupOneScreen(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
216static Bool
217fixupScreens(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
231static Bool
232fixupServerClient(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
240static Bool
241fixupExtensions(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
254static Bool
255fixupDefaultColormaps(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
272static Bool
273fixupDeviceList(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
283static Bool
284fixupDevices(FixupFunc fixup, unsigned bytes)
285{
286 return (fixupDeviceList(inputInfo.devices, fixup, bytes) &&
287 fixupDeviceList(inputInfo.off_devices, fixup, bytes));
288}
289
290static 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
298static void
299grow_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
308static void
309grow_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 */
334Bool
335dixRegisterPrivateKey(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
405Bool
406dixRegisterScreenPrivateKey(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
431DevPrivateKey
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 */
440void
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 */
457void
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 */
471void *
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 */
503Bool
504dixAllocatePrivates(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) {
1
Assuming 'size' is not equal to 0
2
Taking false branch
514 p = NULL((void*)0);
515 }
516 else {
517 if (!(p = malloc(size)))
3
Memory is allocated
4
Assuming 'p' is not null
5
Taking false branch
518 return FALSE0;
519 }
520
521 _dixInitPrivates(privates, p, type);
522 ++global_keys[type].allocated;
6
Potential leak of memory pointed to by 'p'
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 */
533void
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 */
544void
545dixFreePrivates(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 */
555extern _X_EXPORT__attribute__((visibility("default"))) int
556dixPrivatesSize(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 */
565static 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
577int
578dixLookupPrivateOffset(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
600extern _X_EXPORT__attribute__((visibility("default"))) Bool
601dixRegisterScreenSpecificPrivateKey(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 */
642void
643dixFreeScreenSpecificPrivates(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 */
657void
658dixInitScreenSpecificPrivates(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 */
667void
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
689void *
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
725int
726dixScreenSpecificPrivatesSize(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
736void
737dixPrivateUsage(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
758void
759dixResetPrivates(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}