Bug Summary

File:mi/miexpose.c
Location:line 565, column 5
Description:Potential leak of memory pointed to by 'prect'

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
48Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
49
50Permission is hereby granted, free of charge, to any person obtaining a copy
51of this software and associated documentation files (the "Software"), to deal
52in the Software without restriction, including without limitation the rights
53to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
54copies of the Software.
55
56The above copyright notice and this permission notice shall be included in
57all copies or substantial portions of the Software.
58
59THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
62DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
63BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
64WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
65IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
66
67Except as contained in this notice, the name of Digital Equipment Corporation
68shall not be used in advertising or otherwise to promote the sale, use or other
69dealings in this Software without prior written authorization from Digital
70Equipment Corporation.
71
72******************************************************************/
73
74#ifdef HAVE_DIX_CONFIG_H1
75#include <dix-config.h>
76#endif
77
78#include <X11/X.h>
79#include <X11/Xproto.h>
80#include <X11/Xprotostr.h>
81
82#include "misc.h"
83#include "regionstr.h"
84#include "scrnintstr.h"
85#include "gcstruct.h"
86#include "windowstr.h"
87#include "pixmap.h"
88#include "input.h"
89
90#include "dixstruct.h"
91#include "mi.h"
92#include <X11/Xmd.h>
93
94#include "globals.h"
95
96#ifdef PANORAMIX1
97#include "panoramiX.h"
98#include "panoramiXsrv.h"
99#endif
100
101/*
102 machine-independent graphics exposure code. any device that uses
103the region package can call this.
104*/
105
106#ifndef RECTLIMIT25
107#define RECTLIMIT25 25 /* pick a number, any number > 8 */
108#endif
109
110/* miHandleExposures
111 generate a region for exposures for areas that were copied from obscured or
112non-existent areas to non-obscured areas of the destination. Paint the
113background for the region, if the destination is a window.
114
115NOTE:
116 this should generally be called, even if graphicsExposures is false,
117because this is where bits get recovered from backing store.
118
119*/
120
121RegionPtr
122miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
123 GCPtr pGC, int srcx, int srcy, int width, int height,
124 int dstx, int dsty)
125{
126 RegionPtr prgnSrcClip; /* drawable-relative source clip */
127 RegionRec rgnSrcRec;
128 RegionPtr prgnDstClip; /* drawable-relative dest clip */
129 RegionRec rgnDstRec;
130 BoxRec srcBox; /* unclipped source */
131 RegionRec rgnExposed; /* exposed region, calculated source-
132 relative, made dst relative to
133 intersect with visible parts of
134 dest and send events to client,
135 and then screen relative to paint
136 the window background
137 */
138 WindowPtr pSrcWin;
139 BoxRec expBox;
140 Bool extents;
141
142 /* avoid work if we can */
143 if (!pGC->graphicsExposures &&
144 (pDstDrawable->type == DRAWABLE_PIXMAP1) &&
145 ((pSrcDrawable->type == DRAWABLE_PIXMAP1) ||
146 (((WindowPtr) pSrcDrawable)->backStorage == 0)))
147 return NULL((void*)0);
148
149 srcBox.x1 = srcx;
150 srcBox.y1 = srcy;
151 srcBox.x2 = srcx + width;
152 srcBox.y2 = srcy + height;
153
154 if (pSrcDrawable->type != DRAWABLE_PIXMAP1) {
155 BoxRec TsrcBox;
156
157 TsrcBox.x1 = srcx + pSrcDrawable->x;
158 TsrcBox.y1 = srcy + pSrcDrawable->y;
159 TsrcBox.x2 = TsrcBox.x1 + width;
160 TsrcBox.y2 = TsrcBox.y1 + height;
161 pSrcWin = (WindowPtr) pSrcDrawable;
162 if (pGC->subWindowMode == IncludeInferiors1) {
163 prgnSrcClip = NotClippedByChildren(pSrcWin);
164 if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN1) {
165 RegionDestroy(prgnSrcClip);
166 return NULL((void*)0);
167 }
168 }
169 else {
170 if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN1)
171 return NULL((void*)0);
172 prgnSrcClip = &rgnSrcRec;
173 RegionNull(prgnSrcClip);
174 RegionCopy(prgnSrcClip, &pSrcWin->clipList);
175 }
176 RegionTranslate(prgnSrcClip, -pSrcDrawable->x, -pSrcDrawable->y);
177 }
178 else {
179 BoxRec box;
180
181 if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
182 (srcBox.x2 <= pSrcDrawable->width) &&
183 (srcBox.y2 <= pSrcDrawable->height))
184 return NULL((void*)0);
185
186 box.x1 = 0;
187 box.y1 = 0;
188 box.x2 = pSrcDrawable->width;
189 box.y2 = pSrcDrawable->height;
190 prgnSrcClip = &rgnSrcRec;
191 RegionInit(prgnSrcClip, &box, 1);
192 pSrcWin = NULL((void*)0);
193 }
194
195 if (pDstDrawable == pSrcDrawable) {
196 prgnDstClip = prgnSrcClip;
197 }
198 else if (pDstDrawable->type != DRAWABLE_PIXMAP1) {
199 if (pGC->subWindowMode == IncludeInferiors1) {
200 prgnDstClip = NotClippedByChildren((WindowPtr) pDstDrawable);
201 }
202 else {
203 prgnDstClip = &rgnDstRec;
204 RegionNull(prgnDstClip);
205 RegionCopy(prgnDstClip, &((WindowPtr) pDstDrawable)->clipList);
206 }
207 RegionTranslate(prgnDstClip, -pDstDrawable->x, -pDstDrawable->y);
208 }
209 else {
210 BoxRec box;
211
212 box.x1 = 0;
213 box.y1 = 0;
214 box.x2 = pDstDrawable->width;
215 box.y2 = pDstDrawable->height;
216 prgnDstClip = &rgnDstRec;
217 RegionInit(prgnDstClip, &box, 1);
218 }
219
220 /* drawable-relative source region */
221 RegionInit(&rgnExposed, &srcBox, 1);
222
223 /* now get the hidden parts of the source box */
224 RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
225
226 /* move them over the destination */
227 RegionTranslate(&rgnExposed, dstx - srcx, dsty - srcy);
228
229 /* intersect with visible areas of dest */
230 RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
231
232 /* intersect with client clip region. */
233 if (pGC->clientClip)
234 RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);
235
236 /*
237 * If we have LOTS of rectangles, we decide to take the extents
238 * and force an exposure on that. This should require much less
239 * work overall, on both client and server. This is cheating, but
240 * isn't prohibited by the protocol ("spontaneous combustion" :-)
241 * for windows.
242 */
243 extents = pGC->graphicsExposures &&
244 (RegionNumRects(&rgnExposed) > RECTLIMIT25) &&
245 (pDstDrawable->type != DRAWABLE_PIXMAP1);
246 if (pSrcWin) {
247 RegionPtr region;
248
249 if (!(region = wClipShape(pSrcWin)((pSrcWin)->optional ? (pSrcWin)->optional->clipShape
: ((void*)0))
))
250 region = wBoundingShape(pSrcWin)((pSrcWin)->optional ? (pSrcWin)->optional->boundingShape
: ((void*)0))
;
251 /*
252 * If you try to CopyArea the extents of a shaped window, compacting the
253 * exposed region will undo all our work!
254 */
255 if (extents && pSrcWin && region &&
256 (RegionContainsRect(region, &srcBox) != rgnIN1))
257 extents = FALSE0;
258 }
259 if (extents) {
260 expBox = *RegionExtents(&rgnExposed);
261 RegionReset(&rgnExposed, &expBox);
262 }
263 if ((pDstDrawable->type != DRAWABLE_PIXMAP1) &&
264 (((WindowPtr) pDstDrawable)->backgroundState != None0L)) {
265 WindowPtr pWin = (WindowPtr) pDstDrawable;
266
267 /* make the exposed area screen-relative */
268 RegionTranslate(&rgnExposed, pDstDrawable->x, pDstDrawable->y);
269
270 if (extents) {
271 /* miPaintWindow doesn't clip, so we have to */
272 RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
273 }
274 miPaintWindow((WindowPtr) pDstDrawable, &rgnExposed, PW_BACKGROUND0);
275
276 if (extents) {
277 RegionReset(&rgnExposed, &expBox);
278 }
279 else
280 RegionTranslate(&rgnExposed, -pDstDrawable->x, -pDstDrawable->y);
281 }
282 if (prgnDstClip == &rgnDstRec) {
283 RegionUninit(prgnDstClip);
284 }
285 else if (prgnDstClip != prgnSrcClip) {
286 RegionDestroy(prgnDstClip);
287 }
288
289 if (prgnSrcClip == &rgnSrcRec) {
290 RegionUninit(prgnSrcClip);
291 }
292 else {
293 RegionDestroy(prgnSrcClip);
294 }
295
296 if (pGC->graphicsExposures) {
297 /* don't look */
298 RegionPtr exposed = RegionCreate(NullBox((BoxPtr)0), 0);
299
300 *exposed = rgnExposed;
301 return exposed;
302 }
303 else {
304 RegionUninit(&rgnExposed);
305 return NULL((void*)0);
306 }
307}
308
309void
310miSendExposures(WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
311{
312 BoxPtr pBox;
313 int numRects;
314 xEvent *pEvent, *pe;
315 int i;
316
317 pBox = RegionRects(pRgn);
318 numRects = RegionNumRects(pRgn);
319 if (!(pEvent = calloc(1, numRects * sizeof(xEvent))))
320 return;
321
322 for (i = numRects, pe = pEvent; --i >= 0; pe++, pBox++) {
323 pe->u.u.type = Expose12;
324 pe->u.expose.window = pWin->drawable.id;
325 pe->u.expose.x = pBox->x1 - dx;
326 pe->u.expose.y = pBox->y1 - dy;
327 pe->u.expose.width = pBox->x2 - pBox->x1;
328 pe->u.expose.height = pBox->y2 - pBox->y1;
329 pe->u.expose.count = i;
330 }
331
332#ifdef PANORAMIX1
333 if (!noPanoramiXExtension) {
334 int scrnum = pWin->drawable.pScreen->myNum;
335 int x = 0, y = 0;
336 XID realWin = 0;
337
338 if (!pWin->parent) {
339 x = screenInfo.screens[scrnum]->x;
340 y = screenInfo.screens[scrnum]->y;
341 pWin = screenInfo.screens[0]->root;
342 realWin = pWin->drawable.id;
343 }
344 else if (scrnum) {
345 PanoramiXRes *win;
346
347 win = PanoramiXFindIDByScrnum(XRT_WINDOW,
348 pWin->drawable.id, scrnum);
349 if (!win) {
350 free(pEvent);
351 return;
352 }
353 realWin = win->info[0].id;
354 dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess(1<<22));
355 }
356 if (x || y || scrnum)
357 for (i = 0; i < numRects; i++) {
358 pEvent[i].u.expose.window = realWin;
359 pEvent[i].u.expose.x += x;
360 pEvent[i].u.expose.y += y;
361 }
362 }
363#endif
364
365 DeliverEvents(pWin, pEvent, numRects, NullWindow((WindowPtr) 0));
366
367 free(pEvent);
368}
369
370void
371miWindowExposures(WindowPtr pWin, RegionPtr prgn)
372{
373 RegionPtr exposures = prgn;
374
375 if (prgn && !RegionNil(prgn)) {
1
Taking true branch
376 RegionRec expRec;
377 int clientInterested =
378 (pWin->eventMask | wOtherEventMasks(pWin)((pWin)->optional ? (pWin)->optional->otherEventMasks
: 0)
) & ExposureMask(1L<<15);
379 if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT25)) {
380 /*
381 * If we have LOTS of rectangles, we decide to take the extents
382 * and force an exposure on that. This should require much less
383 * work overall, on both client and server. This is cheating, but
384 * isn't prohibited by the protocol ("spontaneous combustion" :-).
385 */
386 BoxRec box;
387
388 box = *RegionExtents(prgn);
389 exposures = &expRec;
390 RegionInit(exposures, &box, 1);
391 RegionReset(prgn, &box);
392 /* miPaintWindow doesn't clip, so we have to */
393 RegionIntersect(prgn, prgn, &pWin->clipList);
394 }
395 miPaintWindow(pWin, prgn, PW_BACKGROUND0);
2
Calling 'miPaintWindow'
396 if (clientInterested)
397 miSendExposures(pWin, exposures,
398 pWin->drawable.x, pWin->drawable.y);
399 if (exposures == &expRec)
400 RegionUninit(exposures);
401 RegionEmpty(prgn);
402 }
403}
404
405#ifdef ROOTLESS1
406/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */
407void RootlessSetPixmapOfAncestors(WindowPtr pWin);
408void RootlessStartDrawing(WindowPtr pWin);
409void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
410Bool IsFramedWindow(WindowPtr pWin);
411#endif
412
413void
414miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
415{
416 ScreenPtr pScreen = pWin->drawable.pScreen;
417 ChangeGCVal gcval[6];
418 BITS32 gcmask;
419 GCPtr pGC;
420 int i;
421 BoxPtr pbox;
422 xRectangle *prect;
423 int numRects;
424
425 /*
426 * Distance from screen to destination drawable, use this
427 * to adjust rendering coordinates which come in in screen space
428 */
429 int draw_x_off, draw_y_off;
430
431 /*
432 * Tile offset for drawing; these need to align the tile
433 * to the appropriate window origin
434 */
435 int tile_x_off, tile_y_off;
436 PixUnion fill;
437 Bool solid = TRUE1;
438 DrawablePtr drawable = &pWin->drawable;
439
440#ifdef ROOTLESS1
441 if (!drawable || drawable->type == UNDRAWABLE_WINDOW2)
3
Taking false branch
442 return;
443
444 if (IsFramedWindow(pWin)) {
4
Taking true branch
445 RootlessStartDrawing(pWin);
446 RootlessDamageRegion(pWin, prgn);
447
448 if (pWin->backgroundState == ParentRelative1L) {
5
Taking false branch
449 if ((what == PW_BACKGROUND0) ||
450 (what == PW_BORDER1 && !pWin->borderIsPixel))
451 RootlessSetPixmapOfAncestors(pWin);
452 }
453 }
454#endif
455
456 if (what == PW_BACKGROUND0) {
6
Taking true branch
457 while (pWin->backgroundState == ParentRelative1L)
7
Loop condition is false. Execution continues on line 460
458 pWin = pWin->parent;
459
460 draw_x_off = drawable->x;
461 draw_y_off = drawable->y;
462
463 tile_x_off = pWin->drawable.x - draw_x_off;
464 tile_y_off = pWin->drawable.y - draw_y_off;
465 fill = pWin->background;
466#ifdef COMPOSITE
467 if (pWin->inhibitBGPaint)
468 return;
469#endif
470 switch (pWin->backgroundState) {
8
'Default' branch taken. Execution continues on line 507
471 case None0L:
472 return;
473 case BackgroundPixmap3L:
474 solid = FALSE0;
475 break;
476 }
477 }
478 else {
479 PixmapPtr pixmap;
480
481 fill = pWin->border;
482 solid = pWin->borderIsPixel;
483
484 /* servers without pixmaps draw their own borders */
485 if (!pScreen->GetWindowPixmap)
486 return;
487 pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
488 drawable = &pixmap->drawable;
489
490 while (pWin->backgroundState == ParentRelative1L)
491 pWin = pWin->parent;
492
493 tile_x_off = pWin->drawable.x;
494 tile_y_off = pWin->drawable.y;
495
496#ifdef COMPOSITE
497 draw_x_off = pixmap->screen_x;
498 draw_y_off = pixmap->screen_y;
499 tile_x_off -= draw_x_off;
500 tile_y_off -= draw_y_off;
501#else
502 draw_x_off = 0;
503 draw_y_off = 0;
504#endif
505 }
506
507 gcval[0].val = GXcopy0x3;
508 gcmask = GCFunction(1L<<0);
509
510#ifdef ROOTLESS_SAFEALPHA1
511/* Bit mask for alpha channel with a particular number of bits per
512 * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
513 * alpha for 16bpp.
514 */
515#define RootlessAlphaMask(bpp)((bpp) == 32 ? 0xFF000000 : 0) ((bpp) == 32 ? 0xFF000000 : 0)
516#endif
517
518 if (solid) {
9
Taking true branch
519#ifdef ROOTLESS_SAFEALPHA1
520 gcval[1].val =
521 fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel)((pWin->drawable.bitsPerPixel) == 32 ? 0xFF000000 : 0);
522#else
523 gcval[1].val = fill.pixel;
524#endif
525 gcval[2].val = FillSolid0;
526 gcmask |= GCForeground(1L<<2) | GCFillStyle(1L<<8);
527 }
528 else {
529 int c = 1;
530
531#ifdef ROOTLESS_SAFEALPHA1
532 gcval[c++].val =
533 ((CARD32) -1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel)((pWin->drawable.bitsPerPixel) == 32 ? 0xFF000000 : 0);
534 gcmask |= GCPlaneMask(1L<<1);
535#endif
536 gcval[c++].val = FillTiled1;
537 gcval[c++].ptr = (void *) fill.pixmap;
538 gcval[c++].val = tile_x_off;
539 gcval[c++].val = tile_y_off;
540 gcmask |= GCFillStyle(1L<<8) | GCTile(1L<<10) | GCTileStipXOrigin(1L<<12) | GCTileStipYOrigin(1L<<13);
541 }
542
543 prect = malloc(RegionNumRects(prgn) * sizeof(xRectangle));
10
Memory is allocated
544 if (!prect)
11
Assuming 'prect' is non-null
12
Taking false branch
545 return;
546
547 pGC = GetScratchGC(drawable->depth, drawable->pScreen);
548 if (!pGC) {
13
Assuming 'pGC' is non-null
14
Taking false branch
549 free(prect);
550 return;
551 }
552
553 ChangeGC(NullClient((ClientPtr) 0), pGC, gcmask, gcval);
554 ValidateGC(drawable, pGC);
555
556 numRects = RegionNumRects(prgn);
557 pbox = RegionRects(prgn);
558 for (i = numRects; --i >= 0; pbox++, prect++) {
15
Loop condition is false. Execution continues on line 564
559 prect->x = pbox->x1 - draw_x_off;
560 prect->y = pbox->y1 - draw_y_off;
561 prect->width = pbox->x2 - pbox->x1;
562 prect->height = pbox->y2 - pbox->y1;
563 }
564 prect -= numRects;
565 (*pGC->ops->PolyFillRect) (drawable, pGC, numRects, prect);
16
Potential leak of memory pointed to by 'prect'
566 free(prect);
567
568 FreeScratchGC(pGC);
569}
570
571/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
572 * the GC. Useful when we have a scratch drawable and need to initialize
573 * it. */
574void
575miClearDrawable(DrawablePtr pDraw, GCPtr pGC)
576{
577 ChangeGCVal fg, bg;
578 xRectangle rect;
579
580 fg.val = pGC->fgPixel;
581 bg.val = pGC->bgPixel;
582 rect.x = 0;
583 rect.y = 0;
584 rect.width = pDraw->width;
585 rect.height = pDraw->height;
586 ChangeGC(NullClient((ClientPtr) 0), pGC, GCForeground(1L<<2), &bg);
587 ValidateGC(pDraw, pGC);
588 (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
589 ChangeGC(NullClient((ClientPtr) 0), pGC, GCForeground(1L<<2), &fg);
590 ValidateGC(pDraw, pGC);
591}