Bug Summary

File:CrCmap.c
Location:line 154, column 9
Description:Access to field 'class' results in a dereference of a null pointer (loaded from variable 'vinfo')

Annotated Source Code

1/*
2
3Copyright 1989, 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
25*/
26
27/*
28 * Author: Donna Converse, MIT X Consortium
29 */
30
31/*
32 * CreateCmap.c - given a standard colormap description, make the map.
33 */
34
35#ifdef HAVE_CONFIG_H1
36#include <config.h>
37#endif
38#include <stdio.h>
39#include <stdlib.h>
40#include <X11/Xlib.h>
41#include <X11/Xutil.h>
42#include <X11/Xmu/StdCmap.h>
43
44/*
45 * Prototypes
46 */
47/* allocate entire map Read Only */
48static int ROmap(Display*, Colormap, unsigned long[], int, int);
49
50/* allocate a cell, prefer Read Only */
51static Statusint ROorRWcell(Display*, Colormap, unsigned long[], int,
52 XColor*, unsigned long);
53
54/* allocate a cell Read Write */
55static Statusint RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
56
57/* for quicksort */
58static int compare(_Xconstconst void*, _Xconstconst void*);
59
60/* find contiguous sequence of cells */
61static Statusint contiguous(unsigned long[], int, int, unsigned long, int*, int*);
62
63/* frees resources before quitting */
64static void free_cells(Display*, Colormap, unsigned long[], int, int);
65
66/* create a map in a RO visual type */
67static Statusint readonly_map(Display*, XVisualInfo*, XStandardColormap*);
68
69/* create a map in a RW visual type */
70static Statusint readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
71
72#define lowbit(x)((x) & (~(x) + 1)) ((x) & (~(x) + 1))
73#define TRUEMATCH(mult,max,mask)(colormap->max * colormap->mult <= vinfo->mask &&
((vinfo->mask) & (~(vinfo->mask) + 1)) == colormap
->mult)
\
74 (colormap->max * colormap->mult <= vinfo->mask && \
75 lowbit(vinfo->mask)((vinfo->mask) & (~(vinfo->mask) + 1)) == colormap->mult)
76
77/*
78 * To create any one colormap which is described by an XStandardColormap
79 * structure, use XmuCreateColormap().
80 *
81 * Return 0 on failure, non-zero on success.
82 * Resources created by this function are not made permanent.
83 * No argument error checking is provided. Use at your own risk.
84 *
85 * All colormaps are created with read only allocations, with the exception
86 * of read only allocations of colors in the default map or otherwise
87 * which fail to return the expected pixel value, and these are individually
88 * defined as read/write allocations. This is done so that all the cells
89 * defined in the default map are contiguous, for use in image processing.
90 * This typically happens with White and Black in the default map.
91 *
92 * Colormaps of static visuals are considered to be successfully created if
93 * the map of the static visual matches the definition given in the
94 * standard colormap structure.
95 */
96
97Statusint
98XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
99 /* dpy - specifies the connection under which the map is created
100 * colormap - specifies the map to be created, and returns, particularly
101 * if the map is created as a subset of the default colormap
102 * of the screen, the base_pixel of the map.
103 */
104{
105 XVisualInfo vinfo_template; /* template visual information */
106 XVisualInfo *vinfo; /* matching visual information */
107 XVisualInfo *vpointer; /* for freeing the entire list */
108 long vinfo_mask; /* specifies the visual mask value */
109 int n; /* number of matching visuals */
110 int status;
111
112 vinfo_template.visualid = colormap->visualid;
113 vinfo_mask = VisualIDMask0x1;
114 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL((void*)0))
1
Taking false branch
115 return 0;
116
117 /* A visual id may be valid on multiple screens. Also, there may
118 * be multiple visuals with identical visual ids at different depths.
119 * If the colormap is the Default Colormap, use the Default Visual.
120 * Otherwise, arbitrarily, use the deepest visual.
121 */
122 vpointer = vinfo;
123 if (n > 1)
2
Assuming 'n' is > 1
3
Taking true branch
124 {
125 register int i;
126 register int screen_number;
127 Boolint def_cmap;
128
129 def_cmap = False0;
130 for (screen_number = ScreenCount(dpy)(((_XPrivDisplay)dpy)->nscreens); --screen_number >= 0; )
4
Loop condition is false. Execution continues on line 136
131 if (colormap->colormap == DefaultColormap(dpy, screen_number)((&((_XPrivDisplay)dpy)->screens[screen_number])->cmap
)
) {
132 def_cmap = True1;
133 break;
134 }
135
136 if (def_cmap) {
5
Taking false branch
137 for (i=0; i < n; i++, vinfo++) {
138 if (vinfo->visual == DefaultVisual(dpy, screen_number)((&((_XPrivDisplay)dpy)->screens[screen_number])->root_visual
)
)
139 break;
140 }
141 } else {
142 int maxdepth = 0;
143 XVisualInfo *v = NULL((void*)0);
144
145 for (i=0; i < n; i++, vinfo++)
6
Loop condition is true. Entering loop body
8
Loop condition is true. Entering loop body
10
Assuming 'i' is >= 'n'
11
Loop condition is false. Execution continues on line 150
146 if (vinfo->depth > maxdepth) {
7
Taking false branch
9
Taking false branch
147 maxdepth = vinfo->depth;
148 v = vinfo;
149 }
150 vinfo = v;
151 }
152 }
153
154 if (vinfo->class == PseudoColor3 || vinfo->class == DirectColor5 ||
12
Access to field 'class' results in a dereference of a null pointer (loaded from variable 'vinfo')
155 vinfo->class == GrayScale1)
156 status = readwrite_map(dpy, vinfo, colormap);
157 else if (vinfo->class == TrueColor4)
158 status = TRUEMATCH(red_mult, red_max, red_mask)(colormap->red_max * colormap->red_mult <= vinfo->
red_mask && ((vinfo->red_mask) & (~(vinfo->
red_mask) + 1)) == colormap->red_mult)
&&
159 TRUEMATCH(green_mult, green_max, green_mask)(colormap->green_max * colormap->green_mult <= vinfo
->green_mask && ((vinfo->green_mask) & (~(vinfo
->green_mask) + 1)) == colormap->green_mult)
&&
160 TRUEMATCH(blue_mult, blue_max, blue_mask)(colormap->blue_max * colormap->blue_mult <= vinfo->
blue_mask && ((vinfo->blue_mask) & (~(vinfo->
blue_mask) + 1)) == colormap->blue_mult)
;
161 else
162 status = readonly_map(dpy, vinfo, colormap);
163
164 XFree((char *) vpointer);
165 return status;
166}
167
168/****************************************************************************/
169static Statusint
170readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
171{
172 register unsigned long i, n; /* index counters */
173 unsigned long ncolors; /* number of colors to be defined */
174 int npixels; /* number of pixels allocated R/W */
175 int first_index; /* first index of pixels to use */
176 int remainder; /* first index of remainder */
177 XColor color; /* the definition of a color */
178 unsigned long *pixels; /* array of colormap pixels */
179 unsigned long delta;
180
181
182 /* Determine ncolors, the number of colors to be defined.
183 * Insure that 1 < ncolors <= the colormap size.
184 */
185 if (vinfo->class == DirectColor5) {
186 ncolors = colormap->red_max;
187 if (colormap->green_max > ncolors)
188 ncolors = colormap->green_max;
189 if (colormap->blue_max > ncolors)
190 ncolors = colormap->blue_max;
191 ncolors++;
192 delta = lowbit(vinfo->red_mask)((vinfo->red_mask) & (~(vinfo->red_mask) + 1)) +
193 lowbit(vinfo->green_mask)((vinfo->green_mask) & (~(vinfo->green_mask) + 1)) +
194 lowbit(vinfo->blue_mask)((vinfo->blue_mask) & (~(vinfo->blue_mask) + 1));
195 } else {
196 ncolors = colormap->red_max * colormap->red_mult +
197 colormap->green_max * colormap->green_mult +
198 colormap->blue_max * colormap->blue_mult + 1;
199 delta = 1;
200 }
201 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
202
203 /* Allocate Read/Write as much of the colormap as we can possibly get.
204 * Then insure that the pixels we were allocated are given in
205 * monotonically increasing order, using a quicksort. Next, insure
206 * that our allocation includes a subset of contiguous pixels at least
207 * as long as the number of colors to be defined. Now we know that
208 * these conditions are met:
209 * 1) There are no free cells in the colormap.
210 * 2) We have a contiguous sequence of pixels, monotonically
211 * increasing, of length >= the number of colors requested.
212 *
213 * One cell at a time, we will free, compute the next color value,
214 * then allocate read only. This takes a long time.
215 * This is done to insure that cells are allocated read only in the
216 * contiguous order which we prefer. If the server has a choice of
217 * cells to grant to an allocation request, the server may give us any
218 * cell, so that is why we do these slow gymnastics.
219 */
220
221 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
222 sizeof(unsigned long))) == NULL((void*)0))
223 return 0;
224
225 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
226 vinfo->colormap_size, ncolors)) == 0) {
227 free((char *) pixels);
228 return 0;
229 }
230
231 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
232
233 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
234 {
235 /* can't find enough contiguous cells, give up */
236 XFreeColors(dpy, colormap->colormap, pixels, npixels,
237 (unsigned long) 0);
238 free((char *) pixels);
239 return 0;
240 }
241 colormap->base_pixel = pixels[first_index];
242
243 /* construct a gray map */
244 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
245 colormap->blue_mult == 1)
246 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
247 {
248 color.pixel = n;
249 color.blue = color.green = color.red =
250 (unsigned short) ((i * 65535) / (colormap->red_max +
251 colormap->green_max +
252 colormap->blue_max));
253
254 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
255 first_index + i))
256 return 0;
257 }
258
259 /* construct a red ramp map */
260 else if (colormap->green_max == 0 && colormap->blue_max == 0)
261 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
262 {
263 color.pixel = n;
264 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
265 color.green = color.blue = 0;
266
267 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
268 first_index + i))
269 return 0;
270 }
271
272 /* construct a green ramp map */
273 else if (colormap->red_max == 0 && colormap->blue_max == 0)
274 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
275 {
276 color.pixel = n;
277 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
278 color.red = color.blue = 0;
279
280 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
281 first_index + i))
282 return 0;
283 }
284
285 /* construct a blue ramp map */
286 else if (colormap->red_max == 0 && colormap->green_max == 0)
287 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
288 {
289 color.pixel = n;
290 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
291 color.red = color.green = 0;
292
293 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
294 first_index + i))
295 return 0;
296 }
297
298 /* construct a standard red green blue cube map */
299 else
300 {
301#define calc(max,mult) (((n / colormap->mult) % \
302 (colormap->max + 1)) * 65535) / colormap->max
303
304 for (n=0, i=0; i < ncolors; i++, n += delta)
305 {
306 color.pixel = n + colormap->base_pixel;
307 color.red = calc(red_max, red_mult);
308 color.green = calc(green_max, green_mult);
309 color.blue = calc(blue_max, blue_mult);
310 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
311 first_index + i))
312 return 0;
313 }
314#undef calc
315 }
316 /* We have a read-only map defined. Now free unused cells,
317 * first those occuring before the contiguous sequence begins,
318 * then any following the contiguous sequence.
319 */
320
321 if (first_index)
322 XFreeColors(dpy, colormap->colormap, pixels, first_index,
323 (unsigned long) 0);
324 if (remainder)
325 XFreeColors(dpy, colormap->colormap,
326 &(pixels[first_index + ncolors]), remainder,
327 (unsigned long) 0);
328
329 free((char *) pixels);
330 return 1;
331}
332
333
334/****************************************************************************/
335static int
336ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
337 /*
338 * dpy - the X server connection
339 * cmap - specifies colormap ID
340 * pixels - returns pixel allocations
341 * m - specifies colormap size
342 * n - specifies number of colors
343 */
344{
345 register int p;
346
347 /* first try to allocate the entire colormap */
348 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL((void*)0),
349 (unsigned) 0, pixels, (unsigned) m))
350 return m;
351
352 /* Allocate all available cells in the colormap, using a binary
353 * algorithm to discover how many cells we can allocate in the colormap.
354 */
355 m--;
356 while (n <= m) {
357 p = n + ((m - n + 1) / 2);
358 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL((void*)0),
359 (unsigned) 0, pixels, (unsigned) p)) {
360 if (p == m)
361 return p;
362 else {
363 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
364 n = p;
365 }
366 }
367 else
368 m = p - 1;
369 }
370 return 0;
371}
372
373
374/****************************************************************************/
375static Statusint
376contiguous(unsigned long pixels[], int npixels, int ncolors,
377 unsigned long delta, int *first, int *rem)
378 /* pixels - specifies allocated pixels
379 * npixels - specifies count of alloc'd pixels
380 * ncolors - specifies needed sequence length
381 * delta - between pixels
382 * first - returns first index of sequence
383 * rem - returns first index after sequence, or 0, if none follow
384 */
385{
386 register int i = 1; /* walking index into the pixel array */
387 register int count = 1; /* length of sequence discovered so far */
388
389 *first = 0;
390 if (npixels == ncolors) {
391 *rem = 0;
392 return 1;
393 }
394 *rem = npixels - 1;
395 while (count < ncolors && ncolors - count <= *rem)
396 {
397 if (pixels[i-1] + delta == pixels[i])
398 count++;
399 else {
400 count = 1;
401 *first = i;
402 }
403 i++;
404 (*rem)--;
405 }
406 if (count != ncolors)
407 return 0;
408 return 1;
409}
410
411
412/****************************************************************************/
413static Statusint
414ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
415 int npixels, XColor *color, unsigned long p)
416{
417 unsigned long pixel;
418 XColor request;
419
420 /* Free the read/write allocation of one cell in the colormap.
421 * Request a read only allocation of one cell in the colormap.
422 * If the read only allocation cannot be granted, give up, because
423 * there must be no free cells in the colormap.
424 * If the read only allocation is granted, but gives us a cell which
425 * is not the one that we just freed, it is probably the case that
426 * we are trying allocate White or Black or some other color which
427 * already has a read-only allocation in the map. So we try to
428 * allocate the previously freed cell with a read/write allocation,
429 * because we want contiguous cells for image processing algorithms.
430 */
431
432 pixel = color->pixel;
433 request.red = color->red;
434 request.green = color->green;
435 request.blue = color->blue;
436
437 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
438 if (! XAllocColor(dpy, cmap, color)
439 || (color->pixel != pixel &&
440 (!RWcell(dpy, cmap, color, &request, &pixel))))
441 {
442 free_cells(dpy, cmap, pixels, npixels, (int)p);
443 return 0;
444 }
445 return 1;
446}
447
448
449/****************************************************************************/
450static void
451free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
452 int npixels, int p)
453 /*
454 * pixels - to be freed
455 * npixels - original number allocated
456 */
457{
458 /* One of the npixels allocated has already been freed.
459 * p is the index of the freed pixel.
460 * First free the pixels preceeding p, and there are p of them;
461 * then free the pixels following p, there are npixels - p - 1 of them.
462 */
463 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
464 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
465 free((char *) pixels);
466}
467
468
469/****************************************************************************/
470static Statusint
471RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
472 unsigned long *pixel)
473{
474 unsigned long n = *pixel;
475
476 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
477 if (! XAllocColorCells(dpy, cmap, (Boolint) 0, (unsigned long *) NULL((void*)0),
478 (unsigned) 0, pixel, (unsigned) 1))
479 return 0;
480 if (*pixel != n)
481 {
482 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
483 return 0;
484 }
485 color->pixel = *pixel;
486 color->flags = DoRed(1<<0) | DoGreen(1<<1) | DoBlue(1<<2);
487 color->red = request->red;
488 color->green = request->green;
489 color->blue = request->blue;
490 XStoreColors(dpy, cmap, color, 1);
491 return 1;
492}
493
494
495/****************************************************************************/
496static int
497compare(_Xconstconst void *e1, _Xconstconst void *e2)
498{
499 return ((int)(*(long *)e1 - *(long *)e2));
500}
501
502
503/****************************************************************************/
504static Statusint
505readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
506{
507 int i, last_pixel;
508 XColor color;
509
510 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
511 (colormap->blue_max + 1) + colormap->base_pixel - 1;
512
513 for(i=colormap->base_pixel; i <= last_pixel; i++) {
514
515 color.pixel = (unsigned long) i;
516 color.red = (unsigned short)
517 (((i/colormap->red_mult) * 65535) / colormap->red_max);
518
519 if (vinfo->class == StaticColor2) {
520 color.green = (unsigned short)
521 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
522 65535) / colormap->green_max);
523 color.blue = (unsigned short)
524 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
525 }
526 else /* vinfo->class == GrayScale, old style allocation XXX */
527 color.green = color.blue = color.red;
528
529 XAllocColor(dpy, colormap->colormap, &color);
530 if (color.pixel != (unsigned long) i)
531 return 0;
532 }
533 return 1;
534}