Bug Summary

File:dix/cursor.c
Location:line 412, column 13
Description:Access to field 'refcnt' results in a dereference of a null pointer (loaded from variable 'sourcefont')

Annotated Source Code

1/***********************************************************
2
3Copyright 1987, 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 in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27 All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Digital not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45******************************************************************/
46
47#ifdef HAVE_DIX_CONFIG_H1
48#include <dix-config.h>
49#endif
50
51#include <X11/X.h>
52#include <X11/Xmd.h>
53#include "servermd.h"
54#include "scrnintstr.h"
55#include "dixstruct.h"
56#include "cursorstr.h"
57#include "dixfontstr.h"
58#include "opaque.h"
59#include "inputstr.h"
60#include "xace.h"
61
62typedef struct _GlyphShare {
63 FontPtr font;
64 unsigned short sourceChar;
65 unsigned short maskChar;
66 CursorBitsPtr bits;
67 struct _GlyphShare *next;
68} GlyphShare, *GlyphSharePtr;
69
70static GlyphSharePtr sharedGlyphs = (GlyphSharePtr) NULL((void*)0);
71
72DevScreenPrivateKeyRec cursorScreenDevPriv;
73
74static CARD32 cursorSerial;
75
76static void
77FreeCursorBits(CursorBitsPtr bits)
78{
79 if (--bits->refcnt > 0)
80 return;
81 free(bits->source);
82 free(bits->mask);
83 free(bits->argb);
84 dixFiniPrivates(bits, PRIVATE_CURSOR_BITS)_dixFiniPrivates((bits)->devPrivates,PRIVATE_CURSOR_BITS);
85 if (bits->refcnt == 0) {
86 GlyphSharePtr *prev, this;
87
88 for (prev = &sharedGlyphs;
89 (this = *prev) && (this->bits != bits); prev = &this->next);
90 if (this) {
91 *prev = this->next;
92 CloseFont(this->font, (Font) 0);
93 free(this);
94 }
95 free(bits);
96 }
97}
98
99/**
100 * To be called indirectly by DeleteResource; must use exactly two args.
101 *
102 * \param value must conform to DeleteType
103 */
104int
105FreeCursor(void *value, XID cid)
106{
107 int nscr;
108 CursorPtr pCurs = (CursorPtr) value;
109
110 ScreenPtr pscr;
111 DeviceIntPtr pDev = NULL((void*)0); /* unused anyway */
112
113
114 UnrefCursor(pCurs);
115 if (CursorRefCount(pCurs) != 0)
116 return Success0;
117
118 BUG_WARN(CursorRefCount(pCurs) < 0)do { if (CursorRefCount(pCurs) < 0) { ErrorFSigSafe("BUG: triggered 'if ("
"CursorRefCount(pCurs) < 0" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n"
, "cursor.c", 118, __func__); if (0) ErrorFSigSafe(((void*)0)
); xorg_backtrace(); } } while(0)
;
119
120 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
121 pscr = screenInfo.screens[nscr];
122 (void) (*pscr->UnrealizeCursor) (pDev, pscr, pCurs);
123 }
124 FreeCursorBits(pCurs->bits);
125 dixFiniPrivates(pCurs, PRIVATE_CURSOR)_dixFiniPrivates((pCurs)->devPrivates,PRIVATE_CURSOR);
126 free(pCurs);
127 return Success0;
128}
129
130CursorPtr
131RefCursor(CursorPtr cursor)
132{
133 if (cursor)
134 cursor->refcnt++;
135 return cursor;
136}
137
138CursorPtr
139UnrefCursor(CursorPtr cursor)
140{
141 if (cursor)
142 cursor->refcnt--;
143 return cursor;
144}
145
146int
147CursorRefCount(const CursorPtr cursor)
148{
149 return cursor ? cursor->refcnt : 0;
150}
151
152
153/*
154 * We check for empty cursors so that we won't have to display them
155 */
156static void
157CheckForEmptyMask(CursorBitsPtr bits)
158{
159 unsigned char *msk = bits->mask;
160 int n = BitmapBytePad(bits->width)(((int)((bits->width) + 32 - 1) >> 5) << 2) * bits->height;
161
162 bits->emptyMask = FALSE0;
163 while (n--)
164 if (*(msk++) != 0)
165 return;
166 if (bits->argb) {
167 CARD32 *argb = bits->argb;
168
169 n = bits->width * bits->height;
170 while (n--)
171 if (*argb++ & 0xff000000)
172 return;
173 }
174 bits->emptyMask = TRUE1;
175}
176
177/**
178 * realize the cursor for every screen. Do not change the refcnt, this will be
179 * changed when ChangeToCursor actually changes the sprite.
180 *
181 * @return Success if all cursors realize on all screens, BadAlloc if realize
182 * failed for a device on a given screen.
183 */
184static int
185RealizeCursorAllScreens(CursorPtr pCurs)
186{
187 DeviceIntPtr pDev;
188 ScreenPtr pscr;
189 int nscr;
190
191 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
192 pscr = screenInfo.screens[nscr];
193 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
194 if (DevHasCursor(pDev)) {
195 if (!(*pscr->RealizeCursor) (pDev, pscr, pCurs)) {
196 /* Realize failed for device pDev on screen pscr.
197 * We have to assume that for all devices before, realize
198 * worked. We need to rollback all devices so far on the
199 * current screen and then all devices on previous
200 * screens.
201 */
202 DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator */
203
204 while (pDevIt && pDevIt != pDev) {
205 if (DevHasCursor(pDevIt))
206 (*pscr->UnrealizeCursor) (pDevIt, pscr, pCurs);
207 pDevIt = pDevIt->next;
208 }
209 while (--nscr >= 0) {
210 pscr = screenInfo.screens[nscr];
211 /* now unrealize all devices on previous screens */
212 pDevIt = inputInfo.devices;
213 while (pDevIt) {
214 if (DevHasCursor(pDevIt))
215 (*pscr->UnrealizeCursor) (pDevIt, pscr, pCurs);
216 pDevIt = pDevIt->next;
217 }
218 (*pscr->UnrealizeCursor) (pDev, pscr, pCurs);
219 }
220 return BadAlloc11;
221 }
222 }
223 }
224 }
225
226 return Success0;
227}
228
229/**
230 * does nothing about the resource table, just creates the data structure.
231 * does not copy the src and mask bits
232 *
233 * \param psrcbits server-defined padding
234 * \param pmaskbits server-defined padding
235 * \param argb no padding
236 */
237int
238AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
239 CARD32 *argb, CursorMetricPtr cm,
240 unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
241 unsigned backRed, unsigned backGreen, unsigned backBlue,
242 CursorPtr *ppCurs, ClientPtr client, XID cid)
243{
244 CursorBitsPtr bits;
245 CursorPtr pCurs;
246 int rc;
247
248 *ppCurs = NULL((void*)0);
249 pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE(sizeof(CursorRec) + dixPrivatesSize(PRIVATE_CURSOR)) + CURSOR_BITS_SIZE(sizeof(CursorBits) + dixPrivatesSize(PRIVATE_CURSOR_BITS)), 1);
250 if (!pCurs)
251 return BadAlloc11;
252
253 bits = (CursorBitsPtr) ((char *) pCurs + CURSOR_REC_SIZE(sizeof(CursorRec) + dixPrivatesSize(PRIVATE_CURSOR)));
254 dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR)_dixInitPrivates(&(pCurs)->devPrivates, (pCurs + 1), PRIVATE_CURSOR
);
;
255 dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)_dixInitPrivates(&(bits)->devPrivates, (bits + 1), PRIVATE_CURSOR_BITS
);
256 bits->source = psrcbits;
257 bits->mask = pmaskbits;
258 bits->argb = argb;
259 bits->width = cm->width;
260 bits->height = cm->height;
261 bits->xhot = cm->xhot;
262 bits->yhot = cm->yhot;
263 pCurs->refcnt = 1;
264 bits->refcnt = -1;
265 CheckForEmptyMask(bits);
266 pCurs->bits = bits;
267 pCurs->serialNumber = ++cursorSerial;
268 pCurs->name = None0L;
269
270 pCurs->foreRed = foreRed;
271 pCurs->foreGreen = foreGreen;
272 pCurs->foreBlue = foreBlue;
273
274 pCurs->backRed = backRed;
275 pCurs->backGreen = backGreen;
276 pCurs->backBlue = backBlue;
277
278 pCurs->id = cid;
279
280 /* security creation/labeling check */
281 rc = XaceHook(XACE_RESOURCE_ACCESS2, client, cid, RT_CURSOR((RESTYPE)5),
282 pCurs, RT_NONE((RESTYPE)0), NULL((void*)0), DixCreateAccess(1<<3));
283 if (rc != Success0)
284 goto error;
285
286 rc = RealizeCursorAllScreens(pCurs);
287 if (rc != Success0)
288 goto error;
289
290 *ppCurs = pCurs;
291 return Success0;
292
293 error:
294 FreeCursorBits(bits);
295 dixFiniPrivates(pCurs, PRIVATE_CURSOR)_dixFiniPrivates((pCurs)->devPrivates,PRIVATE_CURSOR);
296 free(pCurs);
297
298 return rc;
299}
300
301int
302AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
303 unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
304 unsigned backRed, unsigned backGreen, unsigned backBlue,
305 CursorPtr *ppCurs, ClientPtr client, XID cid)
306{
307 FontPtr sourcefont, maskfont;
308 unsigned char *srcbits;
309 unsigned char *mskbits;
310 CursorMetricRec cm;
311 int rc;
312 CursorBitsPtr bits;
313 CursorPtr pCurs;
314 GlyphSharePtr pShare;
315
316 rc = dixLookupResourceByType((void **) &sourcefont, source, RT_FONT((RESTYPE)4),
1
Value assigned to 'sourcefont'
317 client, DixUseAccess(1<<24));
318 if (rc != Success0) {
2
Assuming 'rc' is equal to 0
3
Taking false branch
319 client->errorValue = source;
320 return rc;
321 }
322 rc = dixLookupResourceByType((void **) &maskfont, mask, RT_FONT((RESTYPE)4), client,
323 DixUseAccess(1<<24));
324 if (rc != Success0 && mask != None0L) {
4
Assuming 'rc' is equal to 0
325 client->errorValue = mask;
326 return rc;
327 }
328 if (sourcefont != maskfont)
5
Assuming 'sourcefont' is not equal to 'maskfont'
6
Taking true branch
329 pShare = (GlyphSharePtr) NULL((void*)0);
330 else {
331 for (pShare = sharedGlyphs;
332 pShare &&
333 ((pShare->font != sourcefont) ||
334 (pShare->sourceChar != sourceChar) ||
335 (pShare->maskChar != maskChar)); pShare = pShare->next);
336 }
337 if (pShare) {
7
Taking false branch
338 pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE(sizeof(CursorRec) + dixPrivatesSize(PRIVATE_CURSOR)), 1);
339 if (!pCurs)
340 return BadAlloc11;
341 dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR)_dixInitPrivates(&(pCurs)->devPrivates, (pCurs + 1), PRIVATE_CURSOR
);
;
342 bits = pShare->bits;
343 bits->refcnt++;
344 }
345 else {
346 if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) {
8
Taking false branch
347 client->errorValue = sourceChar;
348 return BadValue2;
349 }
350 if (!maskfont) {
9
Assuming 'maskfont' is null
10
Taking true branch
351 long n;
352 unsigned char *mskptr;
353
354 n = BitmapBytePad(cm.width)(((int)((cm.width) + 32 - 1) >> 5) << 2) * (long) cm.height;
355 mskptr = mskbits = malloc(n);
356 if (!mskptr)
11
Assuming 'mskptr' is non-null
12
Taking false branch
357 return BadAlloc11;
358 while (--n >= 0)
13
Loop condition is false. Execution continues on line 369
359 *mskptr++ = ~0;
360 }
361 else {
362 if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm)) {
363 client->errorValue = maskChar;
364 return BadValue2;
365 }
366 if ((rc = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)))
367 return rc;
368 }
369 if ((rc = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits))) {
14
Assuming 'rc' is zero
15
Taking false branch
370 free(mskbits);
371 return rc;
372 }
373 if (sourcefont != maskfont) {
16
Assuming 'sourcefont' is equal to 'maskfont'
17
Taking false branch
374 pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE(sizeof(CursorRec) + dixPrivatesSize(PRIVATE_CURSOR)) + CURSOR_BITS_SIZE(sizeof(CursorBits) + dixPrivatesSize(PRIVATE_CURSOR_BITS)), 1);
375 if (pCurs)
376 bits = (CursorBitsPtr) ((char *) pCurs + CURSOR_REC_SIZE(sizeof(CursorRec) + dixPrivatesSize(PRIVATE_CURSOR)));
377 else
378 bits = (CursorBitsPtr) NULL((void*)0);
379 }
380 else {
381 pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE(sizeof(CursorRec) + dixPrivatesSize(PRIVATE_CURSOR)), 1);
382 if (pCurs)
18
Assuming 'pCurs' is non-null
19
Taking true branch
383 bits = (CursorBitsPtr) calloc(CURSOR_BITS_SIZE(sizeof(CursorBits) + dixPrivatesSize(PRIVATE_CURSOR_BITS)), 1);
384 else
385 bits = (CursorBitsPtr) NULL((void*)0);
386 }
387 if (!bits) {
20
Assuming 'bits' is non-null
21
Taking false branch
388 free(pCurs);
389 free(mskbits);
390 free(srcbits);
391 return BadAlloc11;
392 }
393 dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR)_dixInitPrivates(&(pCurs)->devPrivates, (pCurs + 1), PRIVATE_CURSOR
);
;
394 dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)_dixInitPrivates(&(bits)->devPrivates, (bits + 1), PRIVATE_CURSOR_BITS
);
;
395 bits->source = srcbits;
396 bits->mask = mskbits;
397 bits->argb = 0;
398 bits->width = cm.width;
399 bits->height = cm.height;
400 bits->xhot = cm.xhot;
401 bits->yhot = cm.yhot;
402 if (sourcefont != maskfont)
22
Taking false branch
403 bits->refcnt = -1;
404 else {
405 bits->refcnt = 1;
406 pShare = malloc(sizeof(GlyphShare));
407 if (!pShare) {
23
Assuming 'pShare' is non-null
24
Taking false branch
408 FreeCursorBits(bits);
409 return BadAlloc11;
410 }
411 pShare->font = sourcefont;
412 sourcefont->refcnt++;
25
Access to field 'refcnt' results in a dereference of a null pointer (loaded from variable 'sourcefont')
413 pShare->sourceChar = sourceChar;
414 pShare->maskChar = maskChar;
415 pShare->bits = bits;
416 pShare->next = sharedGlyphs;
417 sharedGlyphs = pShare;
418 }
419 }
420
421 CheckForEmptyMask(bits);
422 pCurs->bits = bits;
423 pCurs->refcnt = 1;
424 pCurs->serialNumber = ++cursorSerial;
425 pCurs->name = None0L;
426
427 pCurs->foreRed = foreRed;
428 pCurs->foreGreen = foreGreen;
429 pCurs->foreBlue = foreBlue;
430
431 pCurs->backRed = backRed;
432 pCurs->backGreen = backGreen;
433 pCurs->backBlue = backBlue;
434
435 pCurs->id = cid;
436
437 /* security creation/labeling check */
438 rc = XaceHook(XACE_RESOURCE_ACCESS2, client, cid, RT_CURSOR((RESTYPE)5),
439 pCurs, RT_NONE((RESTYPE)0), NULL((void*)0), DixCreateAccess(1<<3));
440 if (rc != Success0)
441 goto error;
442
443 rc = RealizeCursorAllScreens(pCurs);
444 if (rc != Success0)
445 goto error;
446
447 *ppCurs = pCurs;
448 return Success0;
449
450 error:
451 FreeCursorBits(bits);
452 dixFiniPrivates(pCurs, PRIVATE_CURSOR)_dixFiniPrivates((pCurs)->devPrivates,PRIVATE_CURSOR);
453 free(pCurs);
454
455 return rc;
456}
457
458/** CreateRootCursor
459 *
460 * look up the name of a font
461 * open the font
462 * add the font to the resource table
463 * make a cursor from the glyphs
464 * add the cursor to the resource table
465 *************************************************************/
466
467CursorPtr
468CreateRootCursor(char *unused1, unsigned int unused2)
469{
470 CursorPtr curs;
471 FontPtr cursorfont;
472 int err;
473 XID fontID;
474
475 fontID = FakeClientID(0);
476 err = OpenFont(serverClient, fontID, FontLoadAll0x000f | FontOpenSync0x0010,
477 (unsigned) strlen(defaultCursorFont), defaultCursorFont);
478 if (err != Success0)
479 return NullCursor((CursorPtr)((void*)0));
480
481 err = dixLookupResourceByType((void **) &cursorfont, fontID, RT_FONT((RESTYPE)4),
482 serverClient, DixReadAccess(1<<0));
483 if (err != Success0)
484 return NullCursor((CursorPtr)((void*)0));
485 if (AllocGlyphCursor(fontID, 0, fontID, 1, 0, 0, 0, ~0, ~0, ~0,
486 &curs, serverClient, (XID) 0) != Success0)
487 return NullCursor((CursorPtr)((void*)0));
488
489 if (!AddResourceDarwin_X_AddResource(FakeClientID(0), RT_CURSOR((RESTYPE)5), (void *) curs))
490 return NullCursor((CursorPtr)((void*)0));
491
492 return curs;
493}