Bug Summary

File:xftdpy.c
Location:line 54, column 13
Description:Access to field 'next' results in a dereference of a null pointer (loaded from variable 'info')

Annotated Source Code

1/*
2 * Copyright © 2000 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include "xftint.h"
24
25_X_HIDDEN__attribute__((visibility("hidden"))) XftDisplayInfo *_XftDisplayInfo;
26
27static int
28_XftCloseDisplay (Display *dpy, XExtCodes *codes)
29{
30 XftDisplayInfo *info, **prev;
31
32 info = _XftDisplayInfoGet (dpy, FcFalse0);
33 if (!info)
1
Assuming 'info' is non-null
2
Taking false branch
34 return 0;
35
36 /*
37 * Get rid of any dangling unreferenced fonts
38 */
39 info->max_unref_fonts = 0;
40 XftFontManageMemory (dpy);
41
42 /*
43 * Clean up the default values
44 */
45 if (info->defaults)
3
Taking false branch
46 FcPatternDestroy (info->defaults);
47
48 /*
49 * Unhook from the global list
50 */
51 for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
4
Value assigned to 'info'
5
Assuming pointer value is null
6
Loop condition is false. Execution continues on line 54
52 if (info->display == dpy)
53 break;
54 *prev = info->next;
7
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'info')
55
56 free (info);
57 return 0;
58}
59
60
61_X_HIDDEN__attribute__((visibility("hidden"))) XftDisplayInfo *
62_XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary)
63{
64 XftDisplayInfo *info, **prev;
65 XRenderPictFormat pf;
66 int i;
67 int event_base, error_base;
68
69 for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
70 {
71 if (info->display == dpy)
72 {
73 /*
74 * MRU the list
75 */
76 if (prev != &_XftDisplayInfo)
77 {
78 *prev = info->next;
79 info->next = _XftDisplayInfo;
80 _XftDisplayInfo = info;
81 }
82 return info;
83 }
84 }
85 if (!createIfNecessary)
86 return NULL((void*)0);
87
88 info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo));
89 if (!info)
90 goto bail0;
91 info->codes = XAddExtension (dpy);
92 if (!info->codes)
93 goto bail1;
94 (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay);
95
96 info->display = dpy;
97 info->defaults = NULL((void*)0);
98 info->solidFormat = NULL((void*)0);
99 info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
100 (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))((&((_XPrivDisplay)dpy)->screens[(((_XPrivDisplay)dpy)
->default_screen)])->root_visual)
) != NULL((void*)0)));
101 info->use_free_glyphs = FcTrue1;
102 if (info->hasRender)
103 {
104 int major, minor;
105 XRenderQueryVersion (dpy, &major, &minor);
106 if (major < 0 || (major == 0 && minor <= 2))
107 info->use_free_glyphs = FcFalse0;
108
109 info->hasSolid = FcFalse0;
110 if (major > 0 || (major == 0 && minor >= 10))
111 info->hasSolid = FcTrue1;
112
113 pf.type = PictTypeDirect1;
114 pf.depth = 32;
115 pf.direct.redMask = 0xff;
116 pf.direct.greenMask = 0xff;
117 pf.direct.blueMask = 0xff;
118 pf.direct.alphaMask = 0xff;
119 info->solidFormat = XRenderFindFormat (dpy,
120 (PictFormatType(1 << 1)|
121 PictFormatDepth(1 << 2)|
122 PictFormatRedMask(1 << 4)|
123 PictFormatGreenMask(1 << 6)|
124 PictFormatBlueMask(1 << 8)|
125 PictFormatAlphaMask(1 << 10)),
126 &pf,
127 0);
128 }
129 if (XftDebug () & XFT_DBG_RENDER4)
130 {
131 Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy))((&((_XPrivDisplay)dpy)->screens[(((_XPrivDisplay)dpy)
->default_screen)])->root_visual)
;
132 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
133
134 printf ("XftDisplayInfoGet Default visual 0x%x ",
135 (int) visual->visualid);
136 if (format)
137 {
138 if (format->type == PictTypeDirect1)
139 {
140 printf ("format %d,%d,%d,%d\n",
141 format->direct.alpha,
142 format->direct.red,
143 format->direct.green,
144 format->direct.blue);
145 }
146 else
147 {
148 printf ("format indexed\n");
149 }
150 }
151 else
152 printf ("No Render format for default visual\n");
153
154 printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n",
155 info->hasRender ? "True" : "False");
156 }
157 for (i = 0; i < XFT_NUM_SOLID_COLOR16; i++)
158 {
159 info->colors[i].screen = -1;
160 info->colors[i].pict = 0;
161 }
162 info->fonts = NULL((void*)0);
163
164 info->next = _XftDisplayInfo;
165 _XftDisplayInfo = info;
166
167 info->glyph_memory = 0;
168 info->max_glyph_memory = XftDefaultGetInteger (dpy,
169 XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0,
170 XFT_DPY_MAX_GLYPH_MEMORY(4 * 1024 * 1024));
171 if (XftDebug () & XFT_DBG_CACHE128)
172 printf ("global max cache memory %ld\n", info->max_glyph_memory);
173
174
175 info->num_unref_fonts = 0;
176 info->max_unref_fonts = XftDefaultGetInteger (dpy,
177 XFT_MAX_UNREF_FONTS"maxunreffonts", 0,
178 XFT_DPY_MAX_UNREF_FONTS16);
179 if (XftDebug() & XFT_DBG_CACHE128)
180 printf ("global max unref fonts %d\n", info->max_unref_fonts);
181
182 memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH)__builtin___memset_chk (info->fontHash, '\0', sizeof (XftFont
*) * 127, __builtin_object_size (info->fontHash, 0))
;
183 return info;
184
185bail1:
186 free (info);
187bail0:
188 if (XftDebug () & XFT_DBG_RENDER4)
189 {
190 printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n");
191 }
192 return NULL((void*)0);
193}
194
195/*
196 * Reduce memory usage in X server
197 */
198
199static void
200_XftDisplayValidateMemory (XftDisplayInfo *info)
201{
202 XftFont *public;
203 XftFontInt *font;
204 unsigned long glyph_memory;
205
206 glyph_memory = 0;
207 for (public = info->fonts; public; public = font->next)
208 {
209 font = (XftFontInt *) public;
210 glyph_memory += font->glyph_memory;
211 }
212 if (glyph_memory != info->glyph_memory)
213 printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n",
214 info->glyph_memory, glyph_memory);
215}
216
217_X_HIDDEN__attribute__((visibility("hidden"))) void
218_XftDisplayManageMemory (Display *dpy)
219{
220 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0);
221 unsigned long glyph_memory;
222 XftFont *public;
223 XftFontInt *font;
224
225 if (!info || !info->max_glyph_memory)
226 return;
227 if (XftDebug () & XFT_DBG_CACHE128)
228 {
229 if (info->glyph_memory > info->max_glyph_memory)
230 printf ("Reduce global memory from %ld to %ld\n",
231 info->glyph_memory, info->max_glyph_memory);
232 _XftDisplayValidateMemory (info);
233 }
234 while (info->glyph_memory > info->max_glyph_memory)
235 {
236 glyph_memory = rand () % info->glyph_memory;
237 public = info->fonts;
238 while (public)
239 {
240 font = (XftFontInt *) public;
241
242 if (font->glyph_memory > glyph_memory)
243 {
244 _XftFontUncacheGlyph (dpy, public);
245 break;
246 }
247 public = font->next;
248 glyph_memory -= font->glyph_memory;
249 }
250 }
251 if (XftDebug () & XFT_DBG_CACHE128)
252 _XftDisplayValidateMemory (info);
253}
254
255_X_EXPORT__attribute__((visibility("default"))) Boolint
256XftDefaultHasRender (Display *dpy)
257{
258 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1);
259
260 if (!info)
261 return False0;
262 return info->hasRender;
263}
264
265_X_EXPORT__attribute__((visibility("default"))) Boolint
266XftDefaultSet (Display *dpy, FcPattern *defaults)
267{
268 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1);
269
270 if (!info)
271 return False0;
272 if (info->defaults)
273 FcPatternDestroy (info->defaults);
274 info->defaults = defaults;
275 if (!info->max_glyph_memory)
276 info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY(4 * 1024 * 1024);
277 info->max_glyph_memory = XftDefaultGetInteger (dpy,
278 XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0,
279 info->max_glyph_memory);
280 if (!info->max_unref_fonts)
281 info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS16;
282 info->max_unref_fonts = XftDefaultGetInteger (dpy,
283 XFT_MAX_UNREF_FONTS"maxunreffonts", 0,
284 info->max_unref_fonts);
285 return True1;
286}
287
288_X_HIDDEN__attribute__((visibility("hidden"))) int
289XftDefaultParseBool (const char *v)
290{
291 char c0, c1;
292
293 c0 = *v;
294 if (isupper ((int)c0))
295 c0 = tolower (c0);
296 if (c0 == 't' || c0 == 'y' || c0 == '1')
297 return 1;
298 if (c0 == 'f' || c0 == 'n' || c0 == '0')
299 return 0;
300 if (c0 == 'o')
301 {
302 c1 = v[1];
303 if (isupper ((int)c1))
304 c1 = tolower (c1);
305 if (c1 == 'n')
306 return 1;
307 if (c1 == 'f')
308 return 0;
309 }
310 return -1;
311}
312
313static Boolint
314_XftDefaultInitBool (Display *dpy, FcPattern *pat, const char *option)
315{
316 char *v;
317 int i;
318
319 v = XGetDefault (dpy, "Xft", option);
320 if (v && (i = XftDefaultParseBool (v)) >= 0)
321 return FcPatternAddBool (pat, option, i != 0);
322 return True1;
323}
324
325static Boolint
326_XftDefaultInitDouble (Display *dpy, FcPattern *pat, const char *option)
327{
328 char *v, *e;
329 double d;
330
331 v = XGetDefault (dpy, "Xft", option);
332 if (v)
333 {
334 d = strtod (v, &e);
335 if (e != v)
336 return FcPatternAddDouble (pat, option, d);
337 }
338 return True1;
339}
340
341static Boolint
342_XftDefaultInitInteger (Display *dpy, FcPattern *pat, const char *option)
343{
344 char *v, *e;
345 int i;
346
347 v = XGetDefault (dpy, "Xft", option);
348 if (v)
349 {
350 if (FcNameConstant ((FcChar8 *) v, &i))
351 return FcPatternAddInteger (pat, option, i);
352 i = strtol (v, &e, 0);
353 if (e != v)
354 return FcPatternAddInteger (pat, option, i);
355 }
356 return True1;
357}
358
359static FcPattern *
360_XftDefaultInit (Display *dpy)
361{
362 FcPattern *pat;
363
364 pat = FcPatternCreate ();
365 if (!pat)
366 goto bail0;
367
368 if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE"scale"))
369 goto bail1;
370 if (!_XftDefaultInitDouble (dpy, pat, FC_DPI"dpi"))
371 goto bail1;
372 if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER"render"))
373 goto bail1;
374 if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA"rgba"))
375 goto bail1;
376 if (!_XftDefaultInitInteger (dpy, pat, FC_LCD_FILTER"lcdfilter"))
377 goto bail1;
378 if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS"antialias"))
379 goto bail1;
380 if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN"embolden"))
381 goto bail1;
382 if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT"autohint"))
383 goto bail1;
384 if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE"hintstyle"))
385 goto bail1;
386 if (!_XftDefaultInitBool (dpy, pat, FC_HINTING"hinting"))
387 goto bail1;
388 if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE"minspace"))
389 goto bail1;
390 if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY"maxglyphmemory"))
391 goto bail1;
392
393 return pat;
394
395bail1:
396 FcPatternDestroy (pat);
397bail0:
398 return NULL((void*)0);
399}
400
401static FcResult
402_XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v)
403{
404 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1);
405 FcResult r;
406
407 if (!info)
408 return FcResultNoMatch;
409
410 if (!info->defaults)
411 {
412 info->defaults = _XftDefaultInit (dpy);
413 if (!info->defaults)
414 return FcResultNoMatch;
415 }
416 r = FcPatternGet (info->defaults, object, screen, v);
417 if (r == FcResultNoId && screen > 0)
418 r = FcPatternGet (info->defaults, object, 0, v);
419 return r;
420}
421
422_X_HIDDEN__attribute__((visibility("hidden"))) Boolint
423XftDefaultGetBool (Display *dpy, const char *object, int screen, Boolint def)
424{
425 FcResult r;
426 FcValue v;
427
428 r = _XftDefaultGet (dpy, object, screen, &v);
429 if (r != FcResultMatch || v.type != FcTypeBool)
430 return def;
431 return v.u.b;
432}
433
434_X_HIDDEN__attribute__((visibility("hidden"))) int
435XftDefaultGetInteger (Display *dpy, const char *object, int screen, int def)
436{
437 FcResult r;
438 FcValue v;
439
440 r = _XftDefaultGet (dpy, object, screen, &v);
441 if (r != FcResultMatch || v.type != FcTypeInteger)
442 return def;
443 return v.u.i;
444}
445
446_X_HIDDEN__attribute__((visibility("hidden"))) double
447XftDefaultGetDouble (Display *dpy, const char *object, int screen, double def)
448{
449 FcResult r;
450 FcValue v;
451
452 r = _XftDefaultGet (dpy, object, screen, &v);
453 if (r != FcResultMatch || v.type != FcTypeDouble)
454 return def;
455 return v.u.d;
456}
457
458_X_EXPORT__attribute__((visibility("default"))) void
459XftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern)
460{
461 FcValue v;
462 double dpi;
463
464 if (FcPatternGet (pattern, XFT_RENDER"render", 0, &v) == FcResultNoMatch)
465 {
466 FcPatternAddBool (pattern, XFT_RENDER"render",
467 XftDefaultGetBool (dpy, XFT_RENDER"render", screen,
468 XftDefaultHasRender (dpy)));
469 }
470 if (FcPatternGet (pattern, FC_ANTIALIAS"antialias", 0, &v) == FcResultNoMatch)
471 {
472 FcPatternAddBool (pattern, FC_ANTIALIAS"antialias",
473 XftDefaultGetBool (dpy, FC_ANTIALIAS"antialias", screen,
474 True1));
475 }
476 if (FcPatternGet (pattern, FC_EMBOLDEN"embolden", 0, &v) == FcResultNoMatch)
477 {
478 FcPatternAddBool (pattern, FC_EMBOLDEN"embolden",
479 XftDefaultGetBool (dpy, FC_EMBOLDEN"embolden", screen,
480 False0));
481 }
482 if (FcPatternGet (pattern, FC_HINTING"hinting", 0, &v) == FcResultNoMatch)
483 {
484 FcPatternAddBool (pattern, FC_HINTING"hinting",
485 XftDefaultGetBool (dpy, FC_HINTING"hinting", screen,
486 True1));
487 }
488 if (FcPatternGet (pattern, FC_HINT_STYLE"hintstyle", 0, &v) == FcResultNoMatch)
489 {
490 FcPatternAddInteger (pattern, FC_HINT_STYLE"hintstyle",
491 XftDefaultGetInteger (dpy, FC_HINT_STYLE"hintstyle", screen,
492 FC_HINT_FULL3));
493 }
494 if (FcPatternGet (pattern, FC_AUTOHINT"autohint", 0, &v) == FcResultNoMatch)
495 {
496 FcPatternAddBool (pattern, FC_AUTOHINT"autohint",
497 XftDefaultGetBool (dpy, FC_AUTOHINT"autohint", screen,
498 False0));
499 }
500 if (FcPatternGet (pattern, FC_RGBA"rgba", 0, &v) == FcResultNoMatch)
501 {
502 int subpixel = FC_RGBA_UNKNOWN0;
503#if RENDER_MAJOR0 > 0 || RENDER_MINOR11 >= 6
504 if (XftDefaultHasRender (dpy))
505 {
506 int render_order = XRenderQuerySubpixelOrder (dpy, screen);
507 switch (render_order) {
508 default:
509 case SubPixelUnknown0: subpixel = FC_RGBA_UNKNOWN0; break;
510 case SubPixelHorizontalRGB1: subpixel = FC_RGBA_RGB1; break;
511 case SubPixelHorizontalBGR2: subpixel = FC_RGBA_BGR2; break;
512 case SubPixelVerticalRGB3: subpixel = FC_RGBA_VRGB3; break;
513 case SubPixelVerticalBGR4: subpixel = FC_RGBA_VBGR4; break;
514 case SubPixelNone5: subpixel = FC_RGBA_NONE5; break;
515 }
516 }
517#endif
518 FcPatternAddInteger (pattern, FC_RGBA"rgba",
519 XftDefaultGetInteger (dpy, FC_RGBA"rgba", screen,
520 subpixel));
521 }
522 if (FcPatternGet (pattern, FC_LCD_FILTER"lcdfilter", 0, &v) == FcResultNoMatch)
523 {
524 FcPatternAddInteger (pattern, FC_LCD_FILTER"lcdfilter",
525 XftDefaultGetInteger (dpy, FC_LCD_FILTER"lcdfilter", screen,
526 FC_LCD_DEFAULT1));
527 }
528 if (FcPatternGet (pattern, FC_MINSPACE"minspace", 0, &v) == FcResultNoMatch)
529 {
530 FcPatternAddBool (pattern, FC_MINSPACE"minspace",
531 XftDefaultGetBool (dpy, FC_MINSPACE"minspace", screen,
532 False0));
533 }
534 if (FcPatternGet (pattern, FC_DPI"dpi", 0, &v) == FcResultNoMatch)
535 {
536 dpi = (((double) DisplayHeight (dpy, screen)((&((_XPrivDisplay)dpy)->screens[screen])->height) * 25.4) /
537 (double) DisplayHeightMM (dpy, screen)((&((_XPrivDisplay)dpy)->screens[screen])->mheight));
538 FcPatternAddDouble (pattern, FC_DPI"dpi",
539 XftDefaultGetDouble (dpy, FC_DPI"dpi", screen,
540 dpi));
541 }
542 if (FcPatternGet (pattern, FC_SCALE"scale", 0, &v) == FcResultNoMatch)
543 {
544 FcPatternAddDouble (pattern, FC_SCALE"scale",
545 XftDefaultGetDouble (dpy, FC_SCALE"scale", screen, 1.0));
546 }
547 if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0, &v) == FcResultNoMatch)
548 {
549 FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY"maxglyphmemory",
550 XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY"maxglyphmemory",
551 screen,
552 XFT_FONT_MAX_GLYPH_MEMORY(1024 * 1024)));
553 }
554 FcDefaultSubstitute (pattern);
555}
556