diff options
Diffstat (limited to 'source/x/fontconfig/fedora-patches/fontconfig-mt.patch')
-rw-r--r-- | source/x/fontconfig/fedora-patches/fontconfig-mt.patch | 1439 |
1 files changed, 0 insertions, 1439 deletions
diff --git a/source/x/fontconfig/fedora-patches/fontconfig-mt.patch b/source/x/fontconfig/fedora-patches/fontconfig-mt.patch deleted file mode 100644 index 31a3748c..00000000 --- a/source/x/fontconfig/fedora-patches/fontconfig-mt.patch +++ /dev/null @@ -1,1439 +0,0 @@ -From b5bcf61fe789e66df2de609ec246cb7e4d326180 Mon Sep 17 00:00:00 2001 -From: Akira TAGOH <akira@tagoh.org> -Date: Fri, 1 Nov 2019 14:43:42 +0900 -Subject: [PATCH 3/9] Use FcConfigReference/Destroy appropriately instead of - FcConfigGetCurrent - -This may improves to be MT-safe. - -Reported at https://bugs.chromium.org/p/chromium/issues/detail?id=1004254 ---- - doc/fcconfig.fncs | 20 ++++ - fontconfig/fontconfig.h | 4 +- - src/fccache.c | 73 +++++++++--- - src/fccfg.c | 237 ++++++++++++++++++++++++--------------- - src/fcdir.c | 31 ++++- - src/fcinit.c | 15 ++- - src/fclist.c | 25 +++-- - src/fcmatch.c | 48 ++++---- - test/Makefile.am | 5 + - test/run-test.sh | 15 +++ - test/test-crbug1004254.c | 116 +++++++++++++++++++ - 11 files changed, 436 insertions(+), 153 deletions(-) - create mode 100644 test/test-crbug1004254.c - -diff --git a/doc/fcconfig.fncs b/doc/fcconfig.fncs -index 82769d5..e709b54 100644 ---- a/doc/fcconfig.fncs -+++ b/doc/fcconfig.fncs -@@ -174,6 +174,10 @@ Returns one of the two sets of fonts from the configuration as specified - by <parameter>set</parameter>. This font set is owned by the library and must - not be modified or freed. - If <parameter>config</parameter> is NULL, the current configuration is used. -+ </para><para> -+This function isn't MT-safe. <function>FcConfigReference</function> must be called -+before using this and then <function>FcConfigDestroy</function> when -+the return value is no longer referenced. - @@ - - @RET@ FcBlanks * -@@ -407,6 +411,10 @@ parse error, semantic error or allocation failure. Otherwise returns FcTrue. - Obtains the system root directory in 'config' if available. All files - (including file properties in patterns) obtained from this 'config' are - relative to this system root directory. -+ </para><para> -+This function isn't MT-safe. <function>FcConfigReference</function> must be called -+before using this and then <function>FcConfigDestroy</function> when -+the return value is no longer referenced. - @SINCE@ 2.10.92 - @@ - -@@ -433,6 +441,10 @@ When setting this on the current config this causes changing current config - @PURPOSE@ Initialize the iterator - @DESC@ - Initialize 'iter' with the first iterator in the config file information list. -+ </para><para> -+This function isn't MT-safe. <function>FcConfigReference</function> must be called -+before using this and then <function>FcConfigDestroy</function> when the relevant -+values are no longer referenced. - @SINCE@ 2.12.91 - @@ - -@@ -444,6 +456,10 @@ Initialize 'iter' with the first iterator in the config file information list. - @DESC@ - Set 'iter' to point to the next node in the config file information list. - If there is no next node, FcFalse is returned. -+ </para><para> -+This function isn't MT-safe. <function>FcConfigReference</function> must be called -+before using <function>FcConfigFileInfoIterInit</function> and then -+<function>FcConfigDestroy</function> when the relevant values are no longer referenced. - @SINCE@ 2.12.91 - @@ - -@@ -459,5 +475,9 @@ If there is no next node, FcFalse is returned. - Obtain the filename, the description and the flag whether it is enabled or not - for 'iter' where points to current configuration file information. - If the iterator is invalid, FcFalse is returned. -+ </para><para> -+This function isn't MT-safe. <function>FcConfigReference</function> must be called -+before using <function>FcConfigFileInfoIterInit</function> and then -+<function>FcConfigDestroy</function> when the relevant values are no longer referenced. - @SINCE@ 2.12.91 - @@ -diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h -index 2f0e8cf..c795245 100644 ---- a/fontconfig/fontconfig.h -+++ b/fontconfig/fontconfig.h -@@ -375,7 +375,7 @@ FcPublic FcBool - FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose); - - FcPublic void --FcCacheCreateTagFile (const FcConfig *config); -+FcCacheCreateTagFile (FcConfig *config); - - FcPublic FcBool - FcDirCacheCreateUUID (FcChar8 *dir, -@@ -437,7 +437,7 @@ FcPublic FcBlanks * - FcConfigGetBlanks (FcConfig *config); - - FcPublic FcStrList * --FcConfigGetCacheDirs (const FcConfig *config); -+FcConfigGetCacheDirs (FcConfig *config); - - FcPublic int - FcConfigGetRescanInterval (FcConfig *config); -diff --git a/src/fccache.c b/src/fccache.c -index c565560..d8f1dab 100644 ---- a/src/fccache.c -+++ b/src/fccache.c -@@ -58,11 +58,15 @@ FcDirCacheDeleteUUID (const FcChar8 *dir, - { - FcBool ret = FcTrue; - #ifndef _WIN32 -- const FcChar8 *sysroot = FcConfigGetSysRoot (config); -+ const FcChar8 *sysroot; - FcChar8 *target, *d; - struct stat statb; - struct timeval times[2]; - -+ config = FcConfigReference (config); -+ if (!config) -+ return FcFalse; -+ sysroot = FcConfigGetSysRoot (config); - if (sysroot) - d = FcStrBuildFilename (sysroot, dir, NULL); - else -@@ -94,6 +98,7 @@ FcDirCacheDeleteUUID (const FcChar8 *dir, - bail: - FcStrFree (d); - #endif -+ FcConfigDestroy (config); - - return ret; - } -@@ -265,7 +270,13 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) - #endif - FcStrList *list; - FcChar8 *cache_dir; -- const FcChar8 *sysroot = FcConfigGetSysRoot (config); -+ const FcChar8 *sysroot; -+ FcBool ret = FcTrue; -+ -+ config = FcConfigReference (config); -+ if (!config) -+ return FcFalse; -+ sysroot = FcConfigGetSysRoot (config); - - FcDirCacheBasenameMD5 (config, dir, cache_base); - #ifndef _WIN32 -@@ -274,7 +285,10 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) - - list = FcStrListCreate (config->cacheDirs); - if (!list) -- return FcFalse; -+ { -+ ret = FcFalse; -+ goto bail; -+ } - - while ((cache_dir = FcStrListNext (list))) - { -@@ -304,8 +318,11 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) - FcDirCacheDeleteUUID (dir, config); - /* return FcFalse if something went wrong */ - if (cache_dir) -- return FcFalse; -- return FcTrue; -+ ret = FcFalse; -+bail: -+ FcConfigDestroy (config); -+ -+ return ret; - } - - static int -@@ -1041,10 +1058,15 @@ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file) - { - FcCache *cache = NULL; - -+ config = FcConfigReference (config); -+ if (!config) -+ return NULL; - if (!FcDirCacheProcess (config, dir, - FcDirCacheMapHelper, - &cache, cache_file)) -- return NULL; -+ cache = NULL; -+ -+ FcConfigDestroy (config); - - return cache; - } -@@ -1055,13 +1077,16 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) - int fd; - FcCache *cache; - struct stat my_file_stat; -+ FcConfig *config; - - if (!file_stat) - file_stat = &my_file_stat; - fd = FcDirCacheOpenFile (cache_file, file_stat); - if (fd < 0) - return NULL; -- cache = FcDirCacheMapFd (FcConfigGetCurrent (), fd, file_stat, NULL); -+ config = FcConfigReference (NULL); -+ cache = FcDirCacheMapFd (config, fd, file_stat, NULL); -+ FcConfigDestroy (config); - close (fd); - return cache; - } -@@ -1155,12 +1180,16 @@ FcBool - FcDirCacheValid (const FcChar8 *dir) - { - FcConfig *config; -+ FcBool ret; - -- config = FcConfigGetCurrent (); -+ config = FcConfigReference (NULL); - if (!config) - return FcFalse; - -- return FcDirCacheValidConfig (dir, config); -+ ret = FcDirCacheValidConfig (dir, config); -+ FcConfigDestroy (config); -+ -+ return ret; - } - - /* -@@ -1438,9 +1467,13 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose) - FcCache *cache; - struct stat target_stat; - const FcChar8 *sysroot; -+ FcConfig *config; - -+ config = FcConfigReference (NULL); -+ if (!config) -+ return FcFalse; - /* FIXME: this API needs to support non-current FcConfig */ -- sysroot = FcConfigGetSysRoot (NULL); -+ sysroot = FcConfigGetSysRoot (config); - if (sysroot) - dir = FcStrBuildFilename (sysroot, cache_dir, NULL); - else -@@ -1448,7 +1481,8 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose) - if (!dir) - { - fprintf (stderr, "Fontconfig error: %s: out of memory\n", cache_dir); -- return FcFalse; -+ ret = FcFalse; -+ goto bail; - } - if (access ((char *) dir, W_OK) != 0) - { -@@ -1525,8 +1559,10 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose) - } - - closedir (d); -- bail0: -+bail0: - FcStrFree (dir); -+bail: -+ FcConfigDestroy (config); - - return ret; - } -@@ -1968,15 +2004,20 @@ FcDirCacheCreateTagFile (const FcChar8 *cache_dir) - } - - void --FcCacheCreateTagFile (const FcConfig *config) -+FcCacheCreateTagFile (FcConfig *config) - { - FcChar8 *cache_dir = NULL, *d = NULL; - FcStrList *list; -- const FcChar8 *sysroot = FcConfigGetSysRoot (config); -+ const FcChar8 *sysroot; -+ -+ config = FcConfigReference (config); -+ if (!config) -+ return; -+ sysroot = FcConfigGetSysRoot (config); - - list = FcConfigGetCacheDirs (config); - if (!list) -- return; -+ goto bail; - - while ((cache_dir = FcStrListNext (list))) - { -@@ -1992,6 +2033,8 @@ FcCacheCreateTagFile (const FcConfig *config) - if (d) - FcStrFree (d); - FcStrListDone (list); -+bail: -+ FcConfigDestroy (config); - } - - #define __fccache__ -diff --git a/src/fccfg.c b/src/fccfg.c -index 21ccd25..11dc876 100644 ---- a/src/fccfg.c -+++ b/src/fccfg.c -@@ -237,12 +237,12 @@ FcConfigUptoDate (FcConfig *config) - { - FcFileTime config_time, config_dir_time, font_time; - time_t now = time(0); -+ FcBool ret = FcTrue; -+ -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return FcFalse; -- } -+ return FcFalse; -+ - config_time = FcConfigNewestFile (config->configFiles); - config_dir_time = FcConfigNewestFile (config->configDirs); - font_time = FcConfigNewestFile (config->fontDirs); -@@ -258,13 +258,19 @@ FcConfigUptoDate (FcConfig *config) - fprintf (stderr, - "Fontconfig warning: Directory/file mtime in the future. New fonts may not be detected.\n"); - config->rescanTime = now; -- return FcTrue; -+ goto bail; - } - else -- return FcFalse; -+ { -+ ret = FcFalse; -+ goto bail; -+ } - } - config->rescanTime = now; -- return FcTrue; -+bail: -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcExpr * -@@ -291,11 +297,26 @@ FcConfigReference (FcConfig *config) - { - if (!config) - { -- config = FcConfigGetCurrent (); -+ /* Do not use FcConfigGetCurrent () for the purpose of obtaining current FcConfig here. -+ * because the reference counter must be increased before setting it to _fcConfig. -+ */ -+ retry: -+ config = fc_atomic_ptr_get (&_fcConfig); - if (!config) -- return 0; -- } -+ { -+ config = FcConfigCreate (); -+ FcRefInc (&config->ref); - -+ config = FcInitLoadOwnConfigAndFonts (config); -+ if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) -+ { -+ FcConfigDestroy (config); /* To decrease the refcount for the above one. */ -+ FcConfigDestroy (config); /* To destroy it actualy */ -+ goto retry; -+ } -+ return config; -+ } -+ } - FcRefInc (&config->ref); - - return config; -@@ -475,25 +496,32 @@ FcBool - FcConfigBuildFonts (FcConfig *config) - { - FcFontSet *fonts; -+ FcBool ret = FcTrue; - -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return FcFalse; -- } -+ return FcFalse; - - fonts = FcFontSetCreate (); - if (!fonts) -- return FcFalse; -+ { -+ ret = FcFalse; -+ goto bail; -+ } - - FcConfigSetFonts (config, fonts, FcSetSystem); - - if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs)) -- return FcFalse; -+ { -+ ret = FcFalse; -+ goto bail; -+ } - if (FcDebug () & FC_DBG_FONTSET) - FcFontSetPrint (fonts); -- return FcTrue; -+bail: -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcBool -@@ -537,13 +565,15 @@ FcConfigAddConfigDir (FcConfig *config, - FcStrList * - FcConfigGetConfigDirs (FcConfig *config) - { -+ FcStrList *ret; -+ -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -- return FcStrListCreate (config->configDirs); -+ return NULL; -+ ret = FcStrListCreate (config->configDirs); -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcBool -@@ -579,13 +609,15 @@ FcConfigResetFontDirs (FcConfig *config) - FcStrList * - FcConfigGetFontDirs (FcConfig *config) - { -+ FcStrList *ret; -+ -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -- return FcStrListCreate (config->fontDirs); -+ return NULL; -+ ret = FcStrListCreate (config->fontDirs); -+ FcConfigDestroy (config); -+ -+ return ret; - } - - static FcBool -@@ -670,15 +702,17 @@ FcConfigAddCacheDir (FcConfig *config, - } - - FcStrList * --FcConfigGetCacheDirs (const FcConfig *config) -+FcConfigGetCacheDirs (FcConfig *config) - { -+ FcStrList *ret; -+ -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -- return FcStrListCreate (config->cacheDirs); -+ return NULL; -+ ret = FcStrListCreate (config->cacheDirs); -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcBool -@@ -699,13 +733,15 @@ FcConfigAddConfigFile (FcConfig *config, - FcStrList * - FcConfigGetConfigFiles (FcConfig *config) - { -+ FcStrList *ret; -+ -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -- return FcStrListCreate (config->configFiles); -+ return NULL; -+ ret = FcStrListCreate (config->configFiles); -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcChar8 * -@@ -784,25 +820,26 @@ FcConfigAddBlank (FcConfig *config FC_UNUSED, - int - FcConfigGetRescanInterval (FcConfig *config) - { -+ int ret; -+ -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -- return config->rescanInterval; -+ return 0; -+ ret = config->rescanInterval; -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcBool - FcConfigSetRescanInterval (FcConfig *config, int rescanInterval) - { -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return FcFalse; -- } -+ return FcFalse; - config->rescanInterval = rescanInterval; -+ FcConfigDestroy (config); -+ - return FcTrue; - } - -@@ -1670,15 +1707,13 @@ FcConfigSubstituteWithPat (FcConfig *config, - FcBool retval = FcTrue; - FcTest **tst = NULL; - -- if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return FcFalse; -- } -- - if (kind < FcMatchKindBegin || kind >= FcMatchKindEnd) - return FcFalse; -+ -+ config = FcConfigReference (config); -+ if (!config) -+ return FcFalse; -+ - s = config->subst[kind]; - if (kind == FcMatchPattern) - { -@@ -1973,6 +2008,7 @@ bail1: - free (value); - if (tst) - free (tst); -+ FcConfigDestroy (config); - - return retval; - } -@@ -2290,12 +2326,9 @@ FcConfigGetFilename (FcConfig *config, - FcChar8 *file, *dir, **path, **p; - const FcChar8 *sysroot; - -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return NULL; -- } -+ return NULL; - sysroot = FcConfigGetSysRoot (config); - if (!url || !*url) - { -@@ -2306,7 +2339,10 @@ FcConfigGetFilename (FcConfig *config, - file = 0; - - if (FcStrIsAbsoluteFilename(url)) -- return FcConfigFileExists (sysroot, url); -+ { -+ file = FcConfigFileExists (sysroot, url); -+ goto bail; -+ } - - if (*url == '~') - { -@@ -2330,7 +2366,10 @@ FcConfigGetFilename (FcConfig *config, - { - path = FcConfigGetPath (); - if (!path) -- return NULL; -+ { -+ file = NULL; -+ goto bail; -+ } - for (p = path; *p; p++) - { - FcChar8 *s; -@@ -2347,6 +2386,9 @@ FcConfigGetFilename (FcConfig *config, - } - FcConfigFreePath (path); - } -+bail: -+ FcConfigDestroy (config); -+ - return file; - } - -@@ -2409,17 +2451,18 @@ FcConfigAppFontAddFile (FcConfig *config, - FcStrSet *subdirs; - FcStrList *sublist; - FcChar8 *subdir; -+ FcBool ret = FcTrue; - -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return FcFalse; -- } -+ return FcFalse; - - subdirs = FcStrSetCreateEx (FCSS_GROW_BY_64); - if (!subdirs) -- return FcFalse; -+ { -+ ret = FcFalse; -+ goto bail; -+ } - - set = FcConfigGetFonts (config, FcSetApplication); - if (!set) -@@ -2428,7 +2471,8 @@ FcConfigAppFontAddFile (FcConfig *config, - if (!set) - { - FcStrSetDestroy (subdirs); -- return FcFalse; -+ ret = FcFalse; -+ goto bail; - } - FcConfigSetFonts (config, set, FcSetApplication); - } -@@ -2436,7 +2480,8 @@ FcConfigAppFontAddFile (FcConfig *config, - if (!FcFileScanConfig (set, subdirs, file, config)) - { - FcStrSetDestroy (subdirs); -- return FcFalse; -+ ret = FcFalse; -+ goto bail; - } - if ((sublist = FcStrListCreate (subdirs))) - { -@@ -2447,7 +2492,10 @@ FcConfigAppFontAddFile (FcConfig *config, - FcStrListDone (sublist); - } - FcStrSetDestroy (subdirs); -- return FcTrue; -+bail: -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcBool -@@ -2456,17 +2504,18 @@ FcConfigAppFontAddDir (FcConfig *config, - { - FcFontSet *set; - FcStrSet *dirs; -+ FcBool ret = FcTrue; - -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return FcFalse; -- } -+ return FcFalse; - - dirs = FcStrSetCreateEx (FCSS_GROW_BY_64); - if (!dirs) -- return FcFalse; -+ { -+ ret = FcFalse; -+ goto bail; -+ } - - set = FcConfigGetFonts (config, FcSetApplication); - if (!set) -@@ -2475,7 +2524,8 @@ FcConfigAppFontAddDir (FcConfig *config, - if (!set) - { - FcStrSetDestroy (dirs); -- return FcFalse; -+ ret = FcFalse; -+ goto bail; - } - FcConfigSetFonts (config, set, FcSetApplication); - } -@@ -2485,23 +2535,26 @@ FcConfigAppFontAddDir (FcConfig *config, - if (!FcConfigAddDirList (config, FcSetApplication, dirs)) - { - FcStrSetDestroy (dirs); -- return FcFalse; -+ ret = FcFalse; -+ goto bail; - } - FcStrSetDestroy (dirs); -- return FcTrue; -+bail: -+ FcConfigDestroy (config); -+ -+ return ret; - } - - void - FcConfigAppFontClear (FcConfig *config) - { -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return; -- } -+ return; - - FcConfigSetFonts (config, 0, FcSetApplication); -+ -+ FcConfigDestroy (config); - } - - /* -diff --git a/src/fcdir.c b/src/fcdir.c -index 7d7b23c..693c845 100644 ---- a/src/fcdir.c -+++ b/src/fcdir.c -@@ -167,7 +167,16 @@ FcFileScan (FcFontSet *set, - const FcChar8 *file, - FcBool force FC_UNUSED) - { -- return FcFileScanConfig (set, dirs, file, FcConfigGetCurrent ()); -+ FcConfig *config; -+ FcBool ret; -+ -+ config = FcConfigReference (NULL); -+ if (!config) -+ return FcFalse; -+ ret = FcFileScanConfig (set, dirs, file, config); -+ FcConfigDestroy (config); -+ -+ return ret; - } - - /* -@@ -271,10 +280,19 @@ FcDirScan (FcFontSet *set, - const FcChar8 *dir, - FcBool force FC_UNUSED) - { -+ FcConfig *config; -+ FcBool ret; -+ - if (cache || !force) - return FcFalse; - -- return FcDirScanConfig (set, dirs, dir, force, FcConfigGetCurrent ()); -+ config = FcConfigReference (NULL); -+ if (!config) -+ return FcFalse; -+ ret = FcDirScanConfig (set, dirs, dir, force, config); -+ FcConfigDestroy (config); -+ -+ return ret; - } - - /* -@@ -353,12 +371,16 @@ FcDirCacheRescan (const FcChar8 *dir, FcConfig *config) - FcCache *new = NULL; - struct stat dir_stat; - FcStrSet *dirs; -- const FcChar8 *sysroot = FcConfigGetSysRoot (config); -+ const FcChar8 *sysroot; - FcChar8 *d = NULL; - #ifndef _WIN32 - int fd = -1; - #endif - -+ config = FcConfigReference (config); -+ if (!config) -+ return NULL; -+ sysroot = FcConfigGetSysRoot (config); - cache = FcDirCacheLoad (dir, config, NULL); - if (!cache) - goto bail; -@@ -401,6 +423,7 @@ bail1: - bail: - if (d) - FcStrFree (d); -+ FcConfigDestroy (config); - - return new; - } -@@ -413,6 +436,7 @@ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config) - { - FcCache *cache = NULL; - -+ config = FcConfigReference (config); - /* Try to use existing cache file */ - if (!force) - cache = FcDirCacheLoad (dir, config, NULL); -@@ -420,6 +444,7 @@ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config) - /* Not using existing cache file, construct new cache */ - if (!cache) - cache = FcDirCacheScan (dir, config); -+ FcConfigDestroy (config); - - return cache; - } -diff --git a/src/fcinit.c b/src/fcinit.c -index 5831a19..6f82ebd 100644 ---- a/src/fcinit.c -+++ b/src/fcinit.c -@@ -229,7 +229,8 @@ FcInitReinitialize (void) - FcBool - FcInitBringUptoDate (void) - { -- FcConfig *config = FcConfigGetCurrent (); -+ FcConfig *config = FcConfigReference (NULL); -+ FcBool ret = FcTrue; - time_t now; - - if (!config) -@@ -238,19 +239,23 @@ FcInitBringUptoDate (void) - * rescanInterval == 0 disables automatic up to date - */ - if (config->rescanInterval == 0) -- return FcTrue; -+ goto bail; - /* - * Check no more often than rescanInterval seconds - */ - now = time (0); - if (config->rescanTime + config->rescanInterval - now > 0) -- return FcTrue; -+ goto bail; - /* - * If up to date, don't reload configuration - */ - if (FcConfigUptoDate (0)) -- return FcTrue; -- return FcInitReinitialize (); -+ goto bail; -+ ret = FcInitReinitialize (); -+bail: -+ FcConfigDestroy (config); -+ -+ return ret; - } - - #define __fcinit__ -diff --git a/src/fclist.c b/src/fclist.c -index 494bdea..053803b 100644 ---- a/src/fclist.c -+++ b/src/fclist.c -@@ -491,11 +491,10 @@ FcFontSetList (FcConfig *config, - { - if (!FcInitBringUptoDate ()) - goto bail0; -- -- config = FcConfigGetCurrent (); -- if (!config) -- goto bail0; - } -+ config = FcConfigReference (config); -+ if (!config) -+ goto bail0; - FcListHashTableInit (&table); - - if (!os) -@@ -558,7 +557,7 @@ FcFontSetList (FcConfig *config, - */ - ret = FcFontSetCreate (); - if (!ret) -- goto bail0; -+ goto bail1; - for (i = 0; i < FC_LIST_HASH_SIZE; i++) - while ((bucket = table.buckets[i])) - { -@@ -570,6 +569,7 @@ FcFontSetList (FcConfig *config, - - if (destroy_os) - FcObjectSetDestroy (os); -+ FcConfigDestroy (config); - - return ret; - -@@ -577,6 +577,7 @@ bail2: - FcFontSetDestroy (ret); - bail1: - FcListHashTableCleanup (&table); -+ FcConfigDestroy (config); - bail0: - if (destroy_os) - FcObjectSetDestroy (os); -@@ -588,24 +589,26 @@ FcFontList (FcConfig *config, - FcPattern *p, - FcObjectSet *os) - { -- FcFontSet *sets[2]; -+ FcFontSet *sets[2], *ret; - int nsets; - - if (!config) - { - if (!FcInitBringUptoDate ()) - return 0; -- -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; - } -+ config = FcConfigReference (config); -+ if (!config) -+ return NULL; - nsets = 0; - if (config->fonts[FcSetSystem]) - sets[nsets++] = config->fonts[FcSetSystem]; - if (config->fonts[FcSetApplication]) - sets[nsets++] = config->fonts[FcSetApplication]; -- return FcFontSetList (config, sets, nsets, p, os); -+ ret = FcFontSetList (config, sets, nsets, p, os); -+ FcConfigDestroy (config); -+ -+ return ret; - } - #define __fclist__ - #include "fcaliastail.h" -diff --git a/src/fcmatch.c b/src/fcmatch.c -index 78bcf7b..3bc352b 100644 ---- a/src/fcmatch.c -+++ b/src/fcmatch.c -@@ -845,7 +845,7 @@ FcFontSetMatch (FcConfig *config, - FcPattern *p, - FcResult *result) - { -- FcPattern *best; -+ FcPattern *best, *ret = NULL; - - assert (sets != NULL); - assert (p != NULL); -@@ -853,17 +853,16 @@ FcFontSetMatch (FcConfig *config, - - *result = FcResultNoMatch; - -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -+ return NULL; - best = FcFontSetMatchInternal (sets, nsets, p, result); - if (best) -- return FcFontRenderPrepare (config, p, best); -- else -- return NULL; -+ ret = FcFontRenderPrepare (config, p, best); -+ -+ FcConfigDestroy (config); -+ -+ return ret; - } - - FcPattern * -@@ -873,19 +872,16 @@ FcFontMatch (FcConfig *config, - { - FcFontSet *sets[2]; - int nsets; -- FcPattern *best; -+ FcPattern *best, *ret = NULL; - - assert (p != NULL); - assert (result != NULL); - - *result = FcResultNoMatch; - -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -+ return NULL; - nsets = 0; - if (config->fonts[FcSetSystem]) - sets[nsets++] = config->fonts[FcSetSystem]; -@@ -894,9 +890,11 @@ FcFontMatch (FcConfig *config, - - best = FcFontSetMatchInternal (sets, nsets, p, result); - if (best) -- return FcFontRenderPrepare (config, p, best); -- else -- return NULL; -+ ret = FcFontRenderPrepare (config, p, best); -+ -+ FcConfigDestroy (config); -+ -+ return ret; - } - - typedef struct _FcSortNode { -@@ -1183,7 +1181,7 @@ FcFontSort (FcConfig *config, - FcCharSet **csp, - FcResult *result) - { -- FcFontSet *sets[2]; -+ FcFontSet *sets[2], *ret; - int nsets; - - assert (p != NULL); -@@ -1191,18 +1189,18 @@ FcFontSort (FcConfig *config, - - *result = FcResultNoMatch; - -+ config = FcConfigReference (config); - if (!config) -- { -- config = FcConfigGetCurrent (); -- if (!config) -- return 0; -- } -+ return NULL; - nsets = 0; - if (config->fonts[FcSetSystem]) - sets[nsets++] = config->fonts[FcSetSystem]; - if (config->fonts[FcSetApplication]) - sets[nsets++] = config->fonts[FcSetApplication]; -- return FcFontSetSort (config, sets, nsets, p, trim, csp, result); -+ ret = FcFontSetSort (config, sets, nsets, p, trim, csp, result); -+ FcConfigDestroy (config); -+ -+ return ret; - } - #define __fcmatch__ - #include "fcaliastail.h" -diff --git a/test/Makefile.am b/test/Makefile.am -index e44aa0b..aae45cb 100644 ---- a/test/Makefile.am -+++ b/test/Makefile.am -@@ -42,6 +42,11 @@ test_pthread_LDADD = $(top_builddir)/src/libfontconfig.la - # We don't enable this test by default because it will require config and fonts - # to meaningfully test anything, and we are not installed yet. - #TESTS += test-pthread -+ -+check_PROGRAMS += test-crbug1004254 -+test_crbug1004254_LDADD = $(top_builddir)/src/libfontconfig.la -+# Disabling this for the same reason as above but trying to run in run-test.sh. -+#TESTS += test-crbug1004254 - endif - check_PROGRAMS += test-bz89617 - test_bz89617_CFLAGS = \ -diff --git a/test/run-test.sh b/test/run-test.sh -index 8ad09e3..e1ee6d0 100644 ---- a/test/run-test.sh -+++ b/test/run-test.sh -@@ -20,6 +20,8 @@ - # DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. -+set -e -+ - case "$OSTYPE" in - msys ) MyPWD=`pwd -W` ;; # On Msys/MinGW, returns a MS Windows style path. - * ) MyPWD=`pwd` ;; # On any other platforms, returns a Unix style path. -@@ -408,4 +410,17 @@ rm -rf $MYCACHEBASEDIR $MYCONFIG my-fonts.conf my-out my-out.expected - - fi # if [ "x$EXEEXT" = "x" ] - -+if [ -x $BUILDTESTDIR/test-crbug1004254 ]; then -+ dotest "MT-safe global config" -+ prep -+ curl -s -o $FONTDIR/noto.zip https://noto-website-2.storage.googleapis.com/pkgs/NotoSans-hinted.zip -+ (cd $FONTDIR; unzip noto.zip) -+ if [ -n ${SOURCE_DATE_EPOCH:-} ] && [ ${#SOURCE_DATE_EPOCH} -gt 0 ]; then -+ touch -m -t "`date -d \"@${SOURCE_DATE_EPOCH}\" +%y%m%d%H%M.%S`" $FONTDIR -+ fi -+ $BUILDTESTDIR/test-crbug1004254 -+else -+ echo "No test-crbug1004254: skipped" -+fi -+ - rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out -diff --git a/test/test-crbug1004254.c b/test/test-crbug1004254.c -new file mode 100644 -index 0000000..1cc6fc7 ---- /dev/null -+++ b/test/test-crbug1004254.c -@@ -0,0 +1,116 @@ -+/* -+ * fontconfig/test/test-pthread.c -+ * -+ * Copyright © 2000 Keith Packard -+ * Copyright © 2013 Raimund Steger -+ * -+ * Permission to use, copy, modify, distribute, and sell this software and its -+ * documentation for any purpose is hereby granted without fee, provided that -+ * the above copyright notice appear in all copies and that both that -+ * copyright notice and this permission notice appear in supporting -+ * documentation, and that the name of the author(s) not be used in -+ * advertising or publicity pertaining to distribution of the software without -+ * specific, written prior permission. The authors make no -+ * representations about the suitability of this software for any purpose. It -+ * is provided "as is" without express or implied warranty. -+ * -+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR -+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <pthread.h> -+#include <fontconfig/fontconfig.h> -+ -+struct thr_arg_s -+{ -+ int thr_num; -+}; -+ -+static void -+run_query (void) -+{ -+ FcPattern *pat = FcPatternCreate (), *match; -+ FcResult result; -+ -+ FcPatternAddString (pat, FC_FAMILY, "sans-serif"); -+ FcPatternAddBool (pat, FC_SCALABLE, FcTrue); -+ FcConfigSubstitute (NULL, pat, FcMatchPattern); -+ FcDefaultSubstitute (pat); -+ match = FcFontMatch (NULL, pat, &result); -+ if (result != FcResultMatch || !match) -+ { -+ fprintf (stderr, "ERROR: No matches found\n"); -+ } -+ if (match) -+ FcPatternDestroy (match); -+ FcPatternDestroy (pat); -+} -+ -+static void -+run_reinit (void) -+{ -+ if (!FcInitReinitialize ()) -+ { -+ fprintf (stderr, "ERROR: Reinitializing failed\n"); -+ } -+} -+ -+#define NTEST 3000 -+ -+static void * -+run_test_in_thread (void *arg) -+{ -+ struct thr_arg_s *thr_arg = (struct thr_arg_s *) arg; -+ int thread_num = thr_arg->thr_num; -+ -+ fprintf (stderr, "Worker %d: started (round %d)\n", thread_num % 2, thread_num / 2); -+ if ((thread_num % 2) == 0) -+ { -+ run_query (); -+ } -+ else -+ { -+ run_reinit (); -+ } -+ fprintf (stderr, "Worker %d: done (round %d)\n", thread_num % 2, thread_num / 2); -+ -+ return NULL; -+} -+ -+int -+main (int argc, char **argv) -+{ -+ pthread_t threads[NTEST]; -+ struct thr_arg_s thr_arg[NTEST]; -+ int i, j; -+ -+ for (i = 0; i < NTEST; i++) -+ { -+ int result; -+ -+ fprintf (stderr, "Thread %d (worker %d round %d): creating\n", i, i % 2, i / 2); -+ thr_arg[i].thr_num = i; -+ result = pthread_create (&threads[i], NULL, run_test_in_thread, -+ (void *) &thr_arg[i]); -+ if (result != 0) -+ { -+ fprintf (stderr, "Cannot create thread %d\n", i); -+ break; -+ } -+ } -+ for (j = 0; j < i; j++) -+ { -+ pthread_join(threads[j], NULL); -+ fprintf (stderr, "Joined thread %d\n", j); -+ } -+ FcFini (); -+ -+ return 0; -+} --- -2.24.1 - -From aa8c8cfa9fb2563482336249e3f56459099fcf6e Mon Sep 17 00:00:00 2001 -From: Akira TAGOH <akira@tagoh.org> -Date: Sat, 2 Nov 2019 00:14:48 +0900 -Subject: [PATCH 4/9] Fix potential race condition in FcConfigSetCurrent and - FcConfigReference - ---- - src/fccache.c | 2 + - src/fccfg.c | 105 ++++++++++++++++++++++++++++++++++++++++++-------- - 2 files changed, 90 insertions(+), 17 deletions(-) - -diff --git a/src/fccache.c b/src/fccache.c -index d8f1dab..4744a84 100644 ---- a/src/fccache.c -+++ b/src/fccache.c -@@ -1085,6 +1085,8 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) - if (fd < 0) - return NULL; - config = FcConfigReference (NULL); -+ if (!config) -+ return NULL; - cache = FcDirCacheMapFd (config, fd, file_stat, NULL); - FcConfigDestroy (config); - close (fd); -diff --git a/src/fccfg.c b/src/fccfg.c -index 11dc876..30f37af 100644 ---- a/src/fccfg.c -+++ b/src/fccfg.c -@@ -33,6 +33,49 @@ - #endif - - static FcConfig *_fcConfig; /* MT-safe */ -+static FcMutex *_lock; -+ -+static void -+lock_config (void) -+{ -+ FcMutex *lock; -+retry: -+ lock = fc_atomic_ptr_get (&_lock); -+ if (!lock) -+ { -+ lock = (FcMutex *) malloc (sizeof (FcMutex)); -+ FcMutexInit (lock); -+ if (!fc_atomic_ptr_cmpexch (&_lock, NULL, lock)) -+ { -+ FcMutexFinish (lock); -+ goto retry; -+ } -+ FcMutexLock (lock); -+ /* Initialize random state */ -+ FcRandom (); -+ return; -+ } -+ FcMutexLock (lock); -+} -+ -+static void -+unlock_config (void) -+{ -+ FcMutexUnlock (_lock); -+} -+ -+static void -+free_lock (void) -+{ -+ FcMutex *lock; -+ -+ lock = fc_atomic_ptr_get (&_lock); -+ if (lock && fc_atomic_ptr_cmpexch (&_lock, lock, NULL)) -+ { -+ FcMutexFinish (lock); -+ free (lock); -+ } -+} - - static FcConfig * - FcConfigEnsure (void) -@@ -44,8 +87,9 @@ retry: - { - config = FcInitLoadConfigAndFonts (); - -- if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) { -- FcConfigDestroy (config); -+ if (!config || !fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) { -+ if (config) -+ FcConfigDestroy (config); - goto retry; - } - } -@@ -76,6 +120,7 @@ FcConfigFini (void) - FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig); - if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL)) - FcConfigDestroy (cfg); -+ free_lock (); - } - - static FcChar8 * -@@ -297,27 +342,31 @@ FcConfigReference (FcConfig *config) - { - if (!config) - { -- /* Do not use FcConfigGetCurrent () for the purpose of obtaining current FcConfig here. -- * because the reference counter must be increased before setting it to _fcConfig. -+ /* lock during obtaining the value from _fcConfig and count up refcount there, -+ * there are the race between them. - */ -+ lock_config (); - retry: - config = fc_atomic_ptr_get (&_fcConfig); - if (!config) - { -- config = FcConfigCreate (); -- FcRefInc (&config->ref); -+ unlock_config (); - -- config = FcInitLoadOwnConfigAndFonts (config); -+ config = FcInitLoadConfigAndFonts (); -+ if (!config) -+ goto retry; -+ lock_config (); - if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) - { -- FcConfigDestroy (config); /* To decrease the refcount for the above one. */ -- FcConfigDestroy (config); /* To destroy it actualy */ -+ FcConfigDestroy (config); - goto retry; - } -- return config; - } -+ FcRefInc (&config->ref); -+ unlock_config (); - } -- FcRefInc (&config->ref); -+ else -+ FcRefInc (&config->ref); - - return config; - } -@@ -529,20 +578,29 @@ FcConfigSetCurrent (FcConfig *config) - { - FcConfig *cfg; - -+ if (config) -+ { -+ if (!config->fonts[FcSetSystem]) -+ if (!FcConfigBuildFonts (config)) -+ return FcFalse; -+ FcRefInc (&config->ref); -+ } -+ -+ lock_config (); - retry: - cfg = fc_atomic_ptr_get (&_fcConfig); - - if (config == cfg) -+ { -+ unlock_config (); -+ if (config) -+ FcConfigDestroy (config); - return FcTrue; -- -- if (config && !config->fonts[FcSetSystem]) -- if (!FcConfigBuildFonts (config)) -- return FcFalse; -+ } - - if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config)) - goto retry; -- -- FcConfigReference (config); -+ unlock_config (); - if (cfg) - FcConfigDestroy (cfg); - -@@ -2649,7 +2707,9 @@ FcConfigSetSysRoot (FcConfig *config, - { - FcChar8 *s = NULL; - FcBool init = FcFalse; -+ int nretry = 3; - -+retry: - if (!config) - { - /* We can't use FcConfigGetCurrent() here to ensure -@@ -2681,6 +2741,17 @@ FcConfigSetSysRoot (FcConfig *config, - if (init) - { - config = FcInitLoadOwnConfigAndFonts (config); -+ if (!config) -+ { -+ /* Something failed. this is usually unlikely. so retrying */ -+ init = FcFalse; -+ if (--nretry == 0) -+ { -+ fprintf (stderr, "Fontconfig warning: Unable to initialize config and retry limit exceeded. sysroot functionality may not work as expected.\n"); -+ return; -+ } -+ goto retry; -+ } - FcConfigSetCurrent (config); - /* FcConfigSetCurrent() increases the refcount. - * decrease it here to avoid the memory leak. --- -2.24.1 - |