diff -pruN fontconfig-2.10.95.orig/src/fccache.c fontconfig-2.10.95/src/fccache.c --- fontconfig-2.10.95.orig/src/fccache.c 2013-08-26 11:49:32.000000000 +0900 +++ fontconfig-2.10.95/src/fccache.c 2016-08-05 18:01:48.040872110 +0900 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #if defined(HAVE_MMAP) || defined(__CYGWIN__) @@ -547,6 +548,82 @@ FcCacheTimeValid (FcCache *cache, struct return cache->checksum == (int) dir_stat->st_mtime; } +static FcBool +FcCacheOffsetsValid (FcCache *cache) +{ + char *base = (char *)cache; + char *end = base + cache->size; + intptr_t *dirs; + FcFontSet *fs; + int i, j; + + if (cache->dir < 0 || cache->dir > cache->size - sizeof (intptr_t) || + memchr (base + cache->dir, '\0', cache->size - cache->dir) == NULL) + return FcFalse; + + if (cache->dirs < 0 || cache->dirs >= cache->size || + cache->dirs_count < 0 || + cache->dirs_count > (cache->size - cache->dirs) / sizeof (intptr_t)) + return FcFalse; + + dirs = FcCacheDirs (cache); + if (dirs) + { + for (i = 0; i < cache->dirs_count; i++) + { + FcChar8 *dir; + + if (dirs[i] < 0 || + dirs[i] > end - (char *) dirs - sizeof (intptr_t)) + return FcFalse; + + dir = FcOffsetToPtr (dirs, dirs[i], FcChar8); + if (memchr (dir, '\0', end - (char *) dir) == NULL) + return FcFalse; + } + } + + if (cache->set < 0 || cache->set > cache->size - sizeof (FcFontSet)) + return FcFalse; + + fs = FcCacheSet (cache); + if (fs) + { + if (fs->nfont > (end - (char *) fs) / sizeof (FcPattern)) + return FcFalse; + + if (fs->fonts != 0 && !FcIsEncodedOffset(fs->fonts)) + return FcFalse; + + for (i = 0; i < fs->nfont; i++) + { + FcPattern *font = FcFontSetFont (fs, i); + FcPatternElt *e; + FcValueListPtr l; + + if ((char *) font < base || + (char *) font > end - sizeof (FcFontSet) || + font->elts_offset < 0 || + font->elts_offset > end - (char *) font || + font->num > (end - (char *) font - font->elts_offset) / sizeof (FcPatternElt)) + return FcFalse; + + + e = FcPatternElts(font); + if (e->values != 0 && !FcIsEncodedOffset(e->values)) + return FcFalse; + + for (j = font->num, l = FcPatternEltValues(e); j >= 0 && l; j--, l = FcValueListNext(l)) + if (l->next != NULL && !FcIsEncodedOffset(l->next)) + break; + if (j < 0) + return FcFalse; + } + } + + return FcTrue; +} + /* * Map a cache file into memory */ @@ -556,7 +633,8 @@ FcDirCacheMapFd (int fd, struct stat *fd FcCache *cache; FcBool allocated = FcFalse; - if (fd_stat->st_size < (int) sizeof (FcCache)) + if (fd_stat->st_size > INTPTR_MAX || + fd_stat->st_size < (int) sizeof (FcCache)) return NULL; cache = FcCacheFindByStat (fd_stat); if (cache) @@ -612,6 +690,7 @@ FcDirCacheMapFd (int fd, struct stat *fd if (cache->magic != FC_CACHE_MAGIC_MMAP || cache->version < FC_CACHE_CONTENT_VERSION || cache->size != (intptr_t) fd_stat->st_size || + !FcCacheOffsetsValid (cache) || !FcCacheTimeValid (cache, dir_stat) || !FcCacheInsert (cache, fd_stat)) {