Blame SOURCES/fontconfig-validate-offset-in-cache.patch

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