(Once again without the broken ~/.fonts.cache-2 file attached because the message size was too big) If this broken ~/.fonts.cache file exists (and no cache files are in /var/cache/fontconfig) fontconfig (e.g. fc-match) loops endlessly, eating up all system resources. mfabian@magellan:~$ fc-cat .fonts.cache-2 | grep printing fc-cat: printing global cache contents for dir /usr/share/fonts/wine fc-cat: printing global cache contents for dir /usr/share/fonts fc-cat: printing global cache contents for dir /usr/share/fonts/bdf fc-cat: printing global cache contents for dir tmp.xemacs-patches.200505:xemacs-patches.200505.SCORE〓 mfabian@magellan:~$ Don't ask me how that strange last "directory" which doesn't really exist of course got into that cache file. That must be due to yet another weird bug in fontconfig. I have a *file* (not a directory!) with a similar name in the "News" folder in my home directory: mfabian@magellan:~$ ls News/*xemacs-patches.200505* News/nndoc+.tmp.xemacs-patches.200505:xemacs-patches.200505.SCORE mfabian@magellan:~$ But fontconfig has no business in ~/News, it is not listed as a font directory in any config file. Anyway, when reading this broken cache file, fontconfig loops endlessly because the return value of FcCacheReadString () is not checked in fccache.c around line 242: FcCacheReadString (cache->fd, name_buf, sizeof (name_buf)); if (!strlen(name_buf)) break; The return value of FcCacheReadString () is zero because the end of the cache file has been reached but "name_buf" still contains the previous contents, therefore it never breaks (by the way, it might be a good idea to check the return value of the read () a few lines later as well). I've tried to fix this (and also tried to check the return value at the other places where FcCacheReadString () was called, just to make sure). Patch attached.
diff -ru fontconfig-2.3.93.20060127.orig/src/fccache.c fontconfig-2.3.93.20060127/src/fccache.c --- fontconfig-2.3.93.20060127.orig/src/fccache.c 2006-01-27 11:10:27.000000000 +0100 +++ fontconfig-2.3.93.20060127/src/fccache.c 2006-01-27 19:17:33.000000000 +0100 @@ -216,7 +216,8 @@ cache->updated = FcFalse; - FcCacheReadString (cache->fd, name_buf, sizeof (name_buf)); + if (!FcCacheReadString (cache->fd, name_buf, sizeof (name_buf))) + return; if (strcmp (name_buf, FC_GLOBAL_MAGIC_COOKIE) != 0) return; @@ -227,8 +228,9 @@ goto bail_and_destroy; lseek (cache->fd, current_arch_start, SEEK_SET); - FcCacheReadString (cache->fd, candidate_arch_machine_name, - sizeof (candidate_arch_machine_name)); + if (!FcCacheReadString (cache->fd, candidate_arch_machine_name, + sizeof (candidate_arch_machine_name))) + goto bail_and_destroy; if (strlen(candidate_arch_machine_name) == 0) goto bail_and_destroy; @@ -236,8 +238,7 @@ { off_t targ; - FcCacheReadString (cache->fd, name_buf, sizeof (name_buf)); - if (!strlen(name_buf)) + if (!FcCacheReadString (cache->fd, name_buf, sizeof (name_buf)) || !strlen(name_buf)) break; /* Directory must be older than the global cache file; also @@ -700,8 +701,7 @@ return FcTrue; } - FcCacheReadString (fd, name_buf, sizeof (name_buf)); - if (!strlen(name_buf)) + if (!FcCacheReadString (fd, name_buf, sizeof (name_buf)) || !strlen(name_buf)) { FcStrFree ((FcChar8 *)cache_hashed); goto bail; @@ -922,8 +922,7 @@ FcStrFree ((FcChar8 *)cache_file); return -1; } - FcCacheReadString (fd, name_buf, sizeof (name_buf)); - if (!strlen(name_buf)) + if (!FcCacheReadString (fd, name_buf, sizeof (name_buf)) || !strlen(name_buf)) goto bail; name_buf_dir = FcStrDirname ((FcChar8 *)name_buf); @@ -969,7 +968,7 @@ sizeof (candidate_arch_machine_name)) == 0) goto bail1; - while (strlen(FcCacheReadString (fd, subdirName, sizeof (subdirName))) > 0) + while (FcCacheReadString (fd, subdirName, sizeof (subdirName)) && strlen (subdirName) > 0) FcStrSetAdd (dirs, (FcChar8 *)subdirName); if (!FcDirCacheConsume (fd, (const char *)dir, set, config)) @@ -1109,11 +1108,12 @@ fd = open(cache_hashed, O_RDONLY); if (fd == -1) break; - FcCacheReadString (fd, name_buf, sizeof (name_buf)); - close (fd); - - if (!strlen(name_buf)) + if(!FcCacheReadString (fd, name_buf, sizeof (name_buf)) || !strlen(name_buf)) + { + close (fd); break; + } + close (fd); if (strcmp (name_buf, cache_file) != 0) continue;
-- Mike FABIAN <mfabian@xxxxxxx> http://www.suse.de/~mfabian 睡眠不足はいい仕事の敵だ。
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/fontconfig