diff --git a/.fmf/version b/.fmf/version deleted file mode 100644 index d00491f..0000000 --- a/.fmf/version +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/.gitignore b/.gitignore index 8ea9665..807c56c 100644 --- a/.gitignore +++ b/.gitignore @@ -32,15 +32,3 @@ fontconfig-2.8.0.tar.gz /fontconfig-2.13.1.tar.bz2 /fontconfig-2.13.91.tar.xz /fontconfig-2.13.92.tar.xz -/fontconfig-2.13.93.tar.xz -/fontconfig-2.13.94.tar.xz -/fontconfig-2.13.95.tar.xz -/fontconfig-2.13.96.tar.xz -/fontconfig-2.14.0.tar.xz -/fontconfig-2.14.1.tar.xz -/fontconfig-2.14.2.tar.xz -/fontconfig-2.15.0.tar.xz -/fontconfig-2.16.0.tar.xz -/fontconfig-2.16.1.tar.xz -/fontconfig-2.16.2.tar.xz -/fontconfig-2.17.0.tar.xz diff --git a/FcConfigGetFilename.3 b/FcConfigGetFilename.3 new file mode 100644 index 0000000..9450199 --- /dev/null +++ b/FcConfigGetFilename.3 @@ -0,0 +1,25 @@ +.\" auto-generated by docbook2man-spec from docbook-utils package +.TH "FcConfigGetFilename" "3" "27 1月 2020" "Fontconfig 2.13.91" "" +.SH NAME +FcConfigGetFilename \- Find a config file +.SH SYNOPSIS +.nf +\fB#include +.sp +FcChar8 * FcConfigGetFilename (FcConfig *\fIconfig\fB, const FcChar8 *\fIname\fB); +.fi\fR +.SH "DESCRIPTION" +.PP +Given the specified external entity name, return the associated filename. +This provides applications a way to convert various configuration file +references into filename form. +.PP +A null or empty \fIname\fR indicates that the default configuration file should +be used; which file this references can be overridden with the +FONTCONFIG_FILE environment variable. Next, if the name starts with \fI~\fR, it +refers to a file in the current users home directory. Otherwise if the name +doesn't start with '/', it refers to a file in the default configuration +directory; the built-in default directory can be overridden with the +FONTCONFIG_PATH environment variable. +.PP +The result of this function is affected by the FONTCONFIG_SYSROOT environment variable or equivalent functionality. diff --git a/fontconfig-0-timestamp-dir-on-sb.patch b/fontconfig-0-timestamp-dir-on-sb.patch new file mode 100644 index 0000000..cfbc206 --- /dev/null +++ b/fontconfig-0-timestamp-dir-on-sb.patch @@ -0,0 +1,55 @@ +diff --git a/src/fccache.c b/src/fccache.c +index 2d398c73..7139b082 100644 +--- a/src/fccache.c ++++ b/src/fccache.c +@@ -845,7 +845,7 @@ FcCacheTimeValid (FcConfig *config, FcCache *cache, struct stat *dir_stat) + FcCacheDir (cache), cache->checksum, (int) dir_stat->st_mtime); + #endif + +- return cache->checksum == (int) dir_stat->st_mtime && fnano; ++ return dir_stat->st_mtime == 0 || (cache->checksum == (int) dir_stat->st_mtime && fnano); + } + + static FcBool +@@ -1041,17 +1041,39 @@ static FcBool + FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure) + { + FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat); +- struct timeval cache_mtime; ++ struct timeval cache_mtime, zero_mtime = { 0, 0}, dir_mtime; + + if (!cache) + return FcFalse; + cache_mtime.tv_sec = fd_stat->st_mtime; ++ dir_mtime.tv_sec = dir_stat->st_mtime; + #ifdef HAVE_STRUCT_STAT_ST_MTIM + cache_mtime.tv_usec = fd_stat->st_mtim.tv_nsec / 1000; ++ dir_mtime.tv_usec = dir_stat->st_mtim.tv_nsec / 1000; + #else + cache_mtime.tv_usec = 0; ++ dir_mtime.tv_usec = 0; + #endif +- if (timercmp (latest_cache_mtime, &cache_mtime, <)) ++ /* special take care of OSTree */ ++ if (!timercmp (&zero_mtime, &dir_mtime, !=)) ++ { ++ if (!timercmp (&zero_mtime, &cache_mtime, !=)) ++ { ++ if (*((FcCache **) closure)) ++ FcDirCacheUnload (*((FcCache **) closure)); ++ } ++ else if (*((FcCache **) closure) && !timercmp (&zero_mtime, latest_cache_mtime, !=)) ++ { ++ FcDirCacheUnload (cache); ++ return FcFalse; ++ } ++ else if (timercmp (latest_cache_mtime, &cache_mtime, <)) ++ { ++ if (*((FcCache **) closure)) ++ FcDirCacheUnload (*((FcCache **) closure)); ++ } ++ } ++ else if (timercmp (latest_cache_mtime, &cache_mtime, <)) + { + if (*((FcCache **) closure)) + FcDirCacheUnload (*((FcCache **) closure)); diff --git a/fontconfig-disable-network-required-test.patch b/fontconfig-disable-network-required-test.patch deleted file mode 100644 index e048b49..0000000 --- a/fontconfig-disable-network-required-test.patch +++ /dev/null @@ -1,113 +0,0 @@ -diff -pruN fontconfig-2.17.0.orig/test/meson.build fontconfig-2.17.0/test/meson.build ---- fontconfig-2.17.0.orig/test/meson.build 2025-06-27 12:12:04.000000000 +0900 -+++ fontconfig-2.17.0/test/meson.build 2025-06-27 14:41:08.843726446 +0900 -@@ -1,16 +1,16 @@ --fetch_test_fonts = custom_target( -- 'fetch_test_fonts', -- output: 'testfonts', -- command: [ -- python3, -- join_paths(meson.project_source_root(), 'build-aux', 'fetch-testfonts.py'), -- '--target-dir', -- '@BUILD_ROOT@/testfonts', -- '--try-symlink', -- ], -- build_by_default: false, -- build_always_stale: true, --) -+#fetch_test_fonts = custom_target( -+# 'fetch_test_fonts', -+# output: 'testfonts', -+# command: [ -+# python3, -+# join_paths(meson.project_source_root(), 'build-aux', 'fetch-testfonts.py'), -+# '--target-dir', -+# '@BUILD_ROOT@/testfonts', -+# '--try-symlink', -+# ], -+# build_by_default: false, -+# build_always_stale: true, -+#) - - tests = [ - ['test-bz89617.c', {'c_args': ['-DSRCDIR="@0@"'.format(meson.current_source_dir())]}], -@@ -33,7 +33,7 @@ if host_machine.system() != 'windows' - ] - tests_not_parallel += [ - # FIXME: this needs NotoSans-hinted.zip font downloaded and unpacked into test build directory! see run-test.sh -- ['test-crbug1004254.c', {'dependencies': dependency('threads')}], # for pthread -+ # ['test-crbug1004254.c', {'dependencies': dependency('threads')}], # for pthread - ['test-mt-fccfg.c', {'include_directories': include_directories('../src'), 'dependencies': dependency('threads')}], - ] - -@@ -74,10 +74,10 @@ foreach test_data : tests + tests_not_pa - endforeach - - --if get_option('fontations').enabled() -- rust = import('rust') -- rust.test('fc_fontations_rust_tests', fc_fontations, link_with: [libfontconfig_internal], depends: fetch_test_fonts, env: ['builddir=@0@'.format(meson.project_build_root())],) --endif -+#if get_option('fontations').enabled() -+# rust = import('rust') -+# rust.test('fc_fontations_rust_tests', fc_fontations, link_with: [libfontconfig_internal], depends: fetch_test_fonts, env: ['builddir=@0@'.format(meson.project_build_root())],) -+#endif - - fs = import('fs') - -@@ -92,14 +92,14 @@ if host_machine.system() != 'windows' - - test('run_test_sh', find_program('run-test.sh'), timeout: 600, env: ['srcdir=@0@'.format(meson.current_source_dir()), 'builddir=@0@'.format(meson.current_build_dir()), 'EXEEXT=@0@'.format(conf.get('EXEEXT')), 'VERBOSE=1']) - -- if pytest.found() -- test('pytest', pytest, args: ['--tap'], -- workdir: meson.current_source_dir(), -- env: ['builddir=@0@'.format(meson.project_build_root())], -- protocol: 'tap', -- timeout: 600, -- depends: fetch_test_fonts) -- endif -+# if pytest.found() -+# test('pytest', pytest, args: ['--tap'], -+# workdir: meson.current_source_dir(), -+# env: ['builddir=@0@'.format(meson.project_build_root())], -+# protocol: 'tap', -+# timeout: 600, -+# depends: fetch_test_fonts) -+# endif - endif - - if jsonc_dep.found() -diff -pruN fontconfig-2.17.0.orig/test/run-test.sh fontconfig-2.17.0/test/run-test.sh ---- fontconfig-2.17.0.orig/test/run-test.sh 2025-06-27 12:12:04.000000000 +0900 -+++ fontconfig-2.17.0/test/run-test.sh 2025-06-27 14:39:19.098581228 +0900 -@@ -521,18 +521,18 @@ rm -rf "$MYCACHEBASEDIR" "$MYCONFIG" "$B - - 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 "$(fdate ${SOURCE_DATE_EPOCH})" "$FONTDIR" -- fi -- "$BUILDTESTDIR"/test-crbug1004254 --else -+#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 "$(fdate ${SOURCE_DATE_EPOCH})" "$FONTDIR" -+# fi -+# "$BUILDTESTDIR"/test-crbug1004254 -+#else - echo "No test-crbug1004254: skipped" --fi -+#fi - - if [ "x$EXEEXT" = "x" ]; then - diff --git a/fontconfig-drop-lang-from-pkgkit-format.patch b/fontconfig-drop-lang-from-pkgkit-format.patch index abece6d..8b77308 100644 --- a/fontconfig-drop-lang-from-pkgkit-format.patch +++ b/fontconfig-drop-lang-from-pkgkit-format.patch @@ -1,12 +1,12 @@ -diff -pruN fontconfig-2.16.1.orig/src/fcformat.c fontconfig-2.16.1/src/fcformat.c ---- fontconfig-2.16.1.orig/src/fcformat.c 2025-03-13 20:16:47.000000000 +0900 -+++ fontconfig-2.16.1/src/fcformat.c 2025-03-13 20:42:03.633324643 +0900 -@@ -77,7 +77,7 @@ - #define FCCAT_FORMAT "\"%{file|basename|cescape}\" %{index} \"%{-file{%{=unparse|cescape}}}\"" - #define FCMATCH_FORMAT "%{file:-|basename}: \"%{family[0]:-}\" \"%{style[0]:-}\"" - #define FCLIST_FORMAT "%{?file{%{file}: }}%{-file{%{=unparse}}}" --#define PKGKIT_FORMAT "%{[]family{font(%{family|downcase|delete( )})\n}}%{[]lang{font(:lang=%{lang|downcase|translate(_,-)})\n}}" -+#define PKGKIT_FORMAT "%{[]family{font(%{family|downcase|delete( )})\n}}" +diff -pruN fontconfig-2.13.92.orig/src/fcformat.c fontconfig-2.13.92/src/fcformat.c +--- fontconfig-2.13.92.orig/src/fcformat.c 2018-07-19 12:14:39.000000000 +0900 ++++ fontconfig-2.13.92/src/fcformat.c 2020-01-20 13:05:33.626227767 +0900 +@@ -78,7 +78,7 @@ + #define FCCAT_FORMAT "\"%{file|basename|cescape}\" %{index} \"%{-file{%{=unparse|cescape}}}\"" + #define FCMATCH_FORMAT "%{file:-|basename}: \"%{family[0]:-}\" \"%{style[0]:-}\"" + #define FCLIST_FORMAT "%{?file{%{file}: }}%{-file{%{=unparse}}}" +-#define PKGKIT_FORMAT "%{[]family{font(%{family|downcase|delete( )})\n}}%{[]lang{font(:lang=%{lang|downcase|translate(_,-)})\n}}" ++#define PKGKIT_FORMAT "%{[]family{font(%{family|downcase|delete( )})\n}}" + static void - message (const char *fmt, ...) diff --git a/fontconfig-fix-1744377.patch b/fontconfig-fix-1744377.patch new file mode 100644 index 0000000..fda5c2d --- /dev/null +++ b/fontconfig-fix-1744377.patch @@ -0,0 +1,122 @@ +From fcada522913e5e07efa6367eff87ace9f06d24c8 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Wed, 28 Aug 2019 17:46:03 +0900 +Subject: [PATCH] Do not return FcFalse from FcConfigParseAndLoad*() if + complain is set to false + +https://bugzilla.redhat.com/show_bug.cgi?id=1744377 +--- + src/fcxml.c | 8 ++++--- + test/Makefile.am | 4 ++++ + test/test-bz1744377.c | 51 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 60 insertions(+), 3 deletions(-) + create mode 100644 test/test-bz1744377.c + +diff --git a/src/fcxml.c b/src/fcxml.c +index 2e26e77a..076fa301 100644 +--- a/src/fcxml.c ++++ b/src/fcxml.c +@@ -3526,7 +3526,7 @@ _FcConfigParse (FcConfig *config, + int len; + FcStrBuf sbuf; + char buf[BUFSIZ]; +- FcBool ret = FcFalse; ++ FcBool ret = FcFalse, complain_again = complain; + + #ifdef _WIN32 + if (!pGetSystemWindowsDirectory) +@@ -3605,7 +3605,7 @@ _FcConfigParse (FcConfig *config, + close (fd); + + ret = FcConfigParseAndLoadFromMemoryInternal (config, filename, FcStrBufDoneStatic (&sbuf), complain, load); +- complain = FcFalse; /* no need to reclaim here */ ++ complain_again = FcFalse; /* no need to reclaim here */ + bail1: + FcStrBufDestroy (&sbuf); + bail0: +@@ -3613,7 +3613,9 @@ bail0: + FcStrFree (filename); + if (realfilename) + FcStrFree (realfilename); +- if (!ret && complain) ++ if (!complain) ++ return FcTrue; ++ if (!ret && complain_again) + { + if (name) + FcConfigMessage (0, FcSevereError, "Cannot %s config file \"%s\"", load ? "load" : "scan", name); +diff --git a/test/Makefile.am b/test/Makefile.am +index f9c21581..a9fa089a 100644 +--- a/test/Makefile.am ++++ b/test/Makefile.am +@@ -131,6 +131,10 @@ TESTS += test-d1f48f11 + endif + endif + ++check_PROGRAMS += test-bz1744377 ++test_bz1744377_LDADD = $(top_builddir)/src/libfontconfig.la ++TESTS += test-bz1744377 ++ + EXTRA_DIST=run-test.sh run-test-conf.sh $(LOG_COMPILER) $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names + + CLEANFILES=out out1 out2 fonts.conf out.expected +diff --git a/test/test-bz1744377.c b/test/test-bz1744377.c +new file mode 100644 +index 00000000..d7f10535 +--- /dev/null ++++ b/test/test-bz1744377.c +@@ -0,0 +1,51 @@ ++/* ++ * fontconfig/test/test-bz1744377.c ++ * ++ * Copyright © 2000 Keith Packard ++ * ++ * 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 ++ ++int ++main (void) ++{ ++ const FcChar8 *doc = "" ++ "\n" ++ " blahblahblah\n" ++ "\n" ++ ""; ++ const FcChar8 *doc2 = "" ++ "\n" ++ " blahblahblah\n" ++ "\n" ++ ""; ++ FcConfig *cfg = FcConfigCreate (); ++ ++ if (!FcConfigParseAndLoadFromMemory (cfg, doc, FcTrue)) ++ return 1; ++ if (FcConfigParseAndLoadFromMemory (cfg, doc2, FcTrue)) ++ return 1; ++ if (!FcConfigParseAndLoadFromMemory (cfg, doc2, FcFalse)) ++ return 1; ++ ++ FcConfigDestroy (cfg); ++ ++ return 0; ++} +-- +2.23.0 + diff --git a/fontconfig-fix-assertion.patch b/fontconfig-fix-assertion.patch new file mode 100644 index 0000000..2e33736 --- /dev/null +++ b/fontconfig-fix-assertion.patch @@ -0,0 +1,144 @@ +From fbc05949ef52c8a8d69233eed77f6636dffec280 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Wed, 26 Feb 2020 15:42:21 +0900 +Subject: [PATCH] Fix assertion in FcFini() + +Due to the unproper initialization of `latest_mtime', the duplicate caches +was still in fcCacheChains with no references. which means no one frees +them. thus, the memory leak was happened. + +Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/227 +--- + src/fccache.c | 9 +++++---- + src/fcinit.c | 4 ++-- + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/src/fccache.c b/src/fccache.c +index 4744a84..035458e 100644 +--- a/src/fccache.c ++++ b/src/fccache.c +@@ -365,7 +365,6 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + struct stat file_stat, dir_stat; + FcBool ret = FcFalse; + const FcChar8 *sysroot = FcConfigGetSysRoot (config); +- struct timeval latest_mtime = (struct timeval){ 0 }; + + if (sysroot) + d = FcStrBuildFilename (sysroot, dir, NULL); +@@ -390,6 +389,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + #ifndef _WIN32 + FcBool retried = FcFalse; + #endif ++ struct timeval latest_mtime = (struct timeval){ 0 }; ++ + if (sysroot) + cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL); + else +@@ -1081,12 +1082,12 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) + + if (!file_stat) + file_stat = &my_file_stat; +- fd = FcDirCacheOpenFile (cache_file, file_stat); +- if (fd < 0) +- return NULL; + config = FcConfigReference (NULL); + if (!config) + return NULL; ++ fd = FcDirCacheOpenFile (cache_file, file_stat); ++ if (fd < 0) ++ return NULL; + cache = FcDirCacheMapFd (config, fd, file_stat, NULL); + FcConfigDestroy (config); + close (fd); +diff --git a/src/fcinit.c b/src/fcinit.c +index 6f82ebd..0e1421e 100644 +--- a/src/fcinit.c ++++ b/src/fcinit.c +@@ -199,10 +199,10 @@ void + FcFini (void) + { + FcConfigFini (); +- FcCacheFini (); ++ FcConfigPathFini (); + FcDefaultFini (); + FcObjectFini (); +- FcConfigPathFini (); ++ FcCacheFini (); + } + + /* +-- +2.24.1 + +From 6f6b39780215714386606ca1c5457a7106639ff4 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Mon, 23 Mar 2020 14:03:47 +0900 +Subject: [PATCH] Fix assertion in FcCacheFini() again + +The previous fix in fbc05949ef52c8a8d69233eed77f6636dffec280 was wrong. reverting. + +When reading older caches, FcDirCacheMapHelper() returns FcFalse and +it became the return value from FcDirCacheProcess() too, which is wrong. +Actually one of calls for FcDirCacheMapHelper() should be successfully +finished and closure should have a valid pointer for cache. + +Due to this, the proper finalization process wasn't running against +cache in closure. + +Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/227 +--- + src/fccache.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/src/fccache.c b/src/fccache.c +index 035458e..2d398c7 100644 +--- a/src/fccache.c ++++ b/src/fccache.c +@@ -365,6 +365,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + struct stat file_stat, dir_stat; + FcBool ret = FcFalse; + const FcChar8 *sysroot = FcConfigGetSysRoot (config); ++ struct timeval latest_mtime = (struct timeval){ 0 }; + + if (sysroot) + d = FcStrBuildFilename (sysroot, dir, NULL); +@@ -389,7 +390,6 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + #ifndef _WIN32 + FcBool retried = FcFalse; + #endif +- struct timeval latest_mtime = (struct timeval){ 0 }; + + if (sysroot) + cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL); +@@ -445,6 +445,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + } + FcStrListDone (list); + ++ if (closure) ++ return !!(*((FcCache **)closure) != NULL); + return ret; + } + +@@ -792,7 +794,18 @@ FcCacheFini (void) + int i; + + for (i = 0; i < FC_CACHE_MAX_LEVEL; i++) +- assert (fcCacheChains[i] == NULL); ++ { ++ if (FcDebug() & FC_DBG_CACHE) ++ { ++ if (fcCacheChains[i] != NULL) ++ { ++ FcCacheSkip *s = fcCacheChains[i]; ++ printf("Fontconfig error: not freed %p (dir: %s, refcount %d)\n", s->cache, FcCacheDir(s->cache), s->ref.count); ++ } ++ } ++ else ++ assert (fcCacheChains[i] == NULL); ++ } + assert (fcCacheMaxLevel == 0); + + free_lock (); +-- +2.24.1 + diff --git a/fontconfig-fix-crash.patch b/fontconfig-fix-crash.patch deleted file mode 100644 index c52b33d..0000000 --- a/fontconfig-fix-crash.patch +++ /dev/null @@ -1,28 +0,0 @@ -From b9bec06d73340f1b5727302d13ac3df307b7febc Mon Sep 17 00:00:00 2001 -From: Akira TAGOH -Date: Mon, 30 Jun 2025 09:05:18 +0900 -Subject: [PATCH] Fix a heap buffer overflow - -https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/481 - -Changelog: fixed ---- - src/fcfreetype.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/fcfreetype.c b/src/fcfreetype.c -index 7a4d9811..0a87d27a 100644 ---- a/src/fcfreetype.c -+++ b/src/fcfreetype.c -@@ -2661,7 +2661,7 @@ FcFontCapabilities (FT_Face face) - goto bail; - - maxsize = (((FT_ULong)gpos_count + (FT_ULong)gsub_count) * OTLAYOUT_LEN + -- (issilgraphitefont ? strlen(fcSilfCapability) : 0)); -+ (issilgraphitefont ? strlen(fcSilfCapability) + 1: 0)); - complex_ = malloc (sizeof (FcChar8) * maxsize); - if (!complex_) - goto bail; --- -2.50.0 - diff --git a/fontconfig-fix-test.patch b/fontconfig-fix-test.patch new file mode 100644 index 0000000..5ccaaba --- /dev/null +++ b/fontconfig-fix-test.patch @@ -0,0 +1,41 @@ +diff -pruN fontconfig-2.13.92.orig/test/run-test.sh fontconfig-2.13.92/test/run-test.sh +--- fontconfig-2.13.92.orig/test/run-test.sh 2020-01-30 20:19:55.148680493 +0900 ++++ fontconfig-2.13.92/test/run-test.sh 2020-01-30 20:25:48.604550017 +0900 +@@ -409,7 +409,7 @@ rm -rf $MYCACHEBASEDIR $MYCONFIG my-font + + fi # if [ "x$EXEEXT" = "x" ] + +-if [ -x $BUILDTESTDIR/test-crbug1004254 ]; then ++if [ -x $BUILDTESTDIR/test-crbug1004254 ] && [ 0 -eq 1 ]; then + dotest "MT-safe global config" + prep + curl -s -o $FONTDIR/noto.zip https://noto-website-2.storage.googleapis.com/pkgs/NotoSans-hinted.zip +From 8bddcb113779178e5b5ed711db08d9bfbff924cc Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Thu, 5 Dec 2019 19:55:06 +0900 +Subject: [PATCH] Fix a test fail when no bwrap was available + +Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/201 +--- + test/run-test.sh | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/test/run-test.sh b/test/run-test.sh +index e1ee6d0..9b2e54b 100644 +--- a/test/run-test.sh ++++ b/test/run-test.sh +@@ -40,9 +40,8 @@ ECHO=true + FCLIST="$LOG_COMPILER ../fc-list/fc-list$EXEEXT" + FCCACHE="$LOG_COMPILER ../fc-cache/fc-cache$EXEEXT" + +-which bwrap > /dev/null 2>&1 +-if [ $? -eq 0 ]; then +- BWRAP=`which bwrap` ++if [ -x "$(command -v bwrap)" ]; then ++ BWRAP="$(command -v bwrap)" + fi + + FONT1=$TESTDIR/4x6.pcf +-- +2.24.1 + diff --git a/fontconfig-lower-nonlatin-conf.patch b/fontconfig-lower-nonlatin-conf.patch deleted file mode 100644 index 3ff373a..0000000 --- a/fontconfig-lower-nonlatin-conf.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff -pruN fontconfig-2.16.0.orig/conf.d/Makefile.am fontconfig-2.16.0/conf.d/Makefile.am ---- fontconfig-2.16.0.orig/conf.d/Makefile.am 2025-01-18 00:15:05.000000000 +0900 -+++ fontconfig-2.16.0/conf.d/Makefile.am 2025-01-18 00:38:32.245398277 +0900 -@@ -47,7 +47,7 @@ CONF_LINKS = \ - 60-generic.conf \ - 60-latin.conf \ - 65-fonts-persian.conf \ -- 65-nonlatin.conf \ -+ 69-nonlatin.conf \ - 69-unifont.conf \ - 80-delicious.conf \ - 90-synthetic.conf -@@ -95,7 +95,7 @@ template_DATA = \ - 60-latin.conf \ - 65-fonts-persian.conf \ - 65-khmer.conf \ -- 65-nonlatin.conf \ -+ 69-nonlatin.conf \ - 69-unifont.conf \ - 70-no-bitmaps.conf \ - 70-no-bitmaps-and-emoji.conf \ -diff -pruN fontconfig-2.16.0.orig/conf.d/meson.build fontconfig-2.16.0/conf.d/meson.build ---- fontconfig-2.16.0.orig/conf.d/meson.build 2025-01-18 00:15:05.000000000 +0900 -+++ fontconfig-2.16.0/conf.d/meson.build 2025-01-18 00:38:43.243595743 +0900 -@@ -33,7 +33,7 @@ conf_files = [ - '60-latin.conf', - '65-fonts-persian.conf', - '65-khmer.conf', -- '65-nonlatin.conf', -+ '69-nonlatin.conf', - '69-unifont.conf', - '70-no-bitmaps.conf', - '70-no-bitmaps-and-emoji.conf', -@@ -64,7 +64,7 @@ conf_links = [ - '60-generic.conf', - '60-latin.conf', - '65-fonts-persian.conf', -- '65-nonlatin.conf', -+ '69-nonlatin.conf', - '69-unifont.conf', - '80-delicious.conf', - '90-synthetic.conf', diff --git a/fontconfig-mt.patch b/fontconfig-mt.patch new file mode 100644 index 0000000..31a3748 --- /dev/null +++ b/fontconfig-mt.patch @@ -0,0 +1,1439 @@ +From b5bcf61fe789e66df2de609ec246cb7e4d326180 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +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 set. This font set is owned by the library and must + not be modified or freed. + If config is NULL, the current configuration is used. ++ ++This function isn't MT-safe. FcConfigReference must be called ++before using this and then FcConfigDestroy 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. ++ ++This function isn't MT-safe. FcConfigReference must be called ++before using this and then FcConfigDestroy 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. ++ ++This function isn't MT-safe. FcConfigReference must be called ++before using this and then FcConfigDestroy 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. ++ ++This function isn't MT-safe. FcConfigReference must be called ++before using FcConfigFileInfoIterInit and then ++FcConfigDestroy 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. ++ ++This function isn't MT-safe. FcConfigReference must be called ++before using FcConfigFileInfoIterInit and then ++FcConfigDestroy 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 ++#include ++#include ++#include ++#include ++ ++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 +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 + diff --git a/fontconfig-read-latest-cache.patch b/fontconfig-read-latest-cache.patch new file mode 100644 index 0000000..8b70dc0 --- /dev/null +++ b/fontconfig-read-latest-cache.patch @@ -0,0 +1,228 @@ +From c9862b6ea7c3234b29f6500c7d07359847e55ed7 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Mon, 28 Oct 2019 17:11:38 +0900 +Subject: [PATCH 1/9] Read latest cache in paths + +Right now fontconfig uses a cache found first in a path and +cachedirs are the order of the system-wide path and then the user path. +this is due to avoid writing caches into the user path when running as root. + +However, changing caches by certain config only, e.g. using +may not take effect by this behavior, because it may be stored into the user path. + +Thus, needing to find the latest cache out from paths. + +Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/182 +--- + src/fccache.c | 36 +++++++++++++++++++++----- + test/run-test.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 96 insertions(+), 6 deletions(-) + +diff --git a/src/fccache.c b/src/fccache.c +index 0976201..4acde22 100644 +--- a/src/fccache.c ++++ b/src/fccache.c +@@ -338,7 +338,7 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat) + static FcBool + FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat, +- struct stat *dir_stat, void *closure), ++ struct stat *dir_stat, struct timeval *cache_mtime, void *closure), + void *closure, FcChar8 **cache_file_ret) + { + int fd = -1; +@@ -348,6 +348,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + struct stat file_stat, dir_stat; + FcBool ret = FcFalse; + const FcChar8 *sysroot = FcConfigGetSysRoot (config); ++ struct timeval latest_mtime = (struct timeval){ 0 }; + + if (sysroot) + d = FcStrBuildFilename (sysroot, dir, NULL); +@@ -383,15 +384,18 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + #endif + fd = FcDirCacheOpenFile (cache_hashed, &file_stat); + if (fd >= 0) { +- ret = (*callback) (config, fd, &file_stat, &dir_stat, closure); ++ ret = (*callback) (config, fd, &file_stat, &dir_stat, &latest_mtime, closure); + close (fd); + if (ret) + { + if (cache_file_ret) ++ { ++ if (*cache_file_ret) ++ FcStrFree (*cache_file_ret); + *cache_file_ret = cache_hashed; ++ } + else + FcStrFree (cache_hashed); +- break; + } + } + #ifndef _WIN32 +@@ -414,7 +418,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + } + } + #endif +- FcStrFree (cache_hashed); ++ else ++ FcStrFree (cache_hashed); + } + FcStrListDone (list); + +@@ -998,12 +1003,31 @@ FcDirCacheUnload (FcCache *cache) + } + + static FcBool +-FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure) ++FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure) + { + FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat); ++ struct timeval cache_mtime; + + if (!cache) + return FcFalse; ++ cache_mtime.tv_sec = fd_stat->st_mtime; ++#ifdef HAVE_STRUCT_STAT_ST_MTIM ++ cache_mtime.tv_usec = fd_stat->st_mtim.tv_nsec / 1000; ++#else ++ cache_mtime.tv_usec = 0; ++#endif ++ if (timercmp (latest_cache_mtime, &cache_mtime, <)) ++ { ++ if (*((FcCache **) closure)) ++ FcDirCacheUnload (*((FcCache **) closure)); ++ } ++ else ++ { ++ FcDirCacheUnload (cache); ++ return FcFalse; ++ } ++ latest_cache_mtime->tv_sec = cache_mtime.tv_sec; ++ latest_cache_mtime->tv_usec = cache_mtime.tv_usec; + *((FcCache **) closure) = cache; + return FcTrue; + } +@@ -1093,7 +1117,7 @@ FcDirChecksumNano (struct stat *statb) + * the magic number and the size field + */ + static FcBool +-FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED) ++FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure FC_UNUSED) + { + FcBool ret = FcTrue; + FcCache c; +diff --git a/test/run-test.sh b/test/run-test.sh +index 4e5968b..8ad09e3 100644 +--- a/test/run-test.sh ++++ b/test/run-test.sh +@@ -340,6 +340,72 @@ fi + + rm -rf $MyPWD/sysroot + ++dotest "read newer caches when multiple places are allowed to store" ++prep ++cp $FONT1 $FONT2 $FONTDIR ++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 ++MYCACHEBASEDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX` ++MYCACHEDIR=$MYCACHEBASEDIR/cache.dir ++MYOWNCACHEDIR=$MYCACHEBASEDIR/owncache.dir ++MYCONFIG=`mktemp /tmp/fontconfig.XXXXXXXX` ++ ++mkdir -p $MYCACHEDIR ++mkdir -p $MYOWNCACHEDIR ++ ++sed "s!@FONTDIR@!$FONTDIR! ++s!@REMAPDIR@!! ++s!@CACHEDIR@!$MYCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf ++ ++FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE $FONTDIR ++ ++sleep 1 ++cat<$MYCONFIG ++ ++ ++ $FONTDIR/4x6.pcf ++ 8 ++ ++ ++EOF ++sed "s!@FONTDIR@!$FONTDIR! ++s!@REMAPDIR@!$MYCONFIG! ++s!@CACHEDIR@!$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf ++ ++if [ -n ${SOURCE_DATE_EPOCH:-} ]; then ++ old_epoch=${SOURCE_DATE_EPOCH} ++ SOURCE_DATE_EPOCH=`expr $SOURCE_DATE_EPOCH + 1` ++fi ++FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE -f $FONTDIR ++if [ -n ${SOURCE_DATE_EPOCH:-} ]; then ++ SOURCE_DATE_EPOCH=${old_epoch} ++fi ++ ++sed "s!@FONTDIR@!$FONTDIR! ++s!@REMAPDIR@!$MYCONFIG! ++s!@CACHEDIR@!$MYCACHEDIR$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf ++ ++FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort > my-out ++echo "=" >> my-out ++FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out ++echo "=" >> my-out ++FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out ++tr -d '\015' my-out.tmp; mv my-out.tmp my-out ++sed -e 's/pixelsize=6/pixelsize=8/g' $BUILDTESTDIR/$EXPECTED > my-out.expected ++ ++if cmp my-out my-out.expected > /dev/null ; then : ; else ++ echo "*** Test failed: $TEST" ++ echo "*** output is in 'my-out', expected output in 'my-out.expected'" ++ echo "Actual Result" ++ cat my-out ++ echo "Expected Result" ++ cat my-out.expected ++ exit 1 ++fi ++ ++rm -rf $MYCACHEBASEDIR $MYCONFIG my-fonts.conf my-out my-out.expected ++ + fi # if [ "x$EXEEXT" = "x" ] + + rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out +-- +2.24.1 + +From a45fc8a33256d9d3ea0ea7947f33c8e5e3cc7238 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Thu, 31 Oct 2019 16:15:25 +0900 +Subject: [PATCH 2/9] Fix a memory leak caused by the previous commit + +--- + src/fccache.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/fccache.c b/src/fccache.c +index 4acde22..c565560 100644 +--- a/src/fccache.c ++++ b/src/fccache.c +@@ -397,6 +397,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + else + FcStrFree (cache_hashed); + } ++ else ++ FcStrFree (cache_hashed); + } + #ifndef _WIN32 + else if (!retried) +@@ -416,6 +418,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, + break; + goto retry; + } ++ else ++ FcStrFree (cache_hashed); + } + #endif + else +-- +2.24.1 + diff --git a/fontconfig-required-freetype-version.patch b/fontconfig-required-freetype-version.patch new file mode 100644 index 0000000..6f7aae3 --- /dev/null +++ b/fontconfig-required-freetype-version.patch @@ -0,0 +1,14 @@ +diff -pruN fontconfig-2.12.93.orig/configure.ac fontconfig-2.12.93/configure.ac +--- fontconfig-2.12.93.orig/configure.ac 2018-02-15 22:01:54.000000000 +0900 ++++ fontconfig-2.12.93/configure.ac 2018-02-15 22:33:42.353941393 +0900 +@@ -308,8 +308,8 @@ AC_DEFINE_UNQUOTED(USE_ICONV,$use_iconv, + # Checks for FreeType + # + dnl See http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/VERSIONS.TXT for versioning in freetype +-PKG_CHECK_MODULES(FREETYPE, freetype2 >= 21.0.15) +-PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES freetype2 >= 21.0.15" ++PKG_CHECK_MODULES(FREETYPE, freetype2 >= 20.0.14) ++PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES freetype2 >= 20.0.14" + + AC_SUBST(FREETYPE_LIBS) + AC_SUBST(FREETYPE_CFLAGS) diff --git a/fontconfig-score-hint-on-match.patch b/fontconfig-score-hint-on-match.patch new file mode 100644 index 0000000..404d7be --- /dev/null +++ b/fontconfig-score-hint-on-match.patch @@ -0,0 +1,36 @@ +From cb1036a7c7f1cb79fa799b1db368c86b018ec368 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Fri, 9 Aug 2019 12:22:08 +0000 +Subject: [PATCH] Affect FC_FONT_HAS_HINT property to score on matcher + +--- + src/fcmatch.c | 1 + + src/fcobjs.h | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/fcmatch.c b/src/fcmatch.c +index c3d2b8ad..78bcf7b4 100644 +--- a/src/fcmatch.c ++++ b/src/fcmatch.c +@@ -342,6 +342,7 @@ typedef enum _FcMatcherPriority { + PRI1(SLANT), + PRI1(WEIGHT), + PRI1(WIDTH), ++ PRI1(FONT_HAS_HINT), + PRI1(DECORATIVE), + PRI1(ANTIALIAS), + PRI1(RASTERIZER), +diff --git a/src/fcobjs.h b/src/fcobjs.h +index 7bb97d09..dd4a6ec3 100644 +--- a/src/fcobjs.h ++++ b/src/fcobjs.h +@@ -72,5 +72,5 @@ FC_OBJECT (COLOR, FcTypeBool, FcCompareBool) + FC_OBJECT (SYMBOL, FcTypeBool, FcCompareBool) + FC_OBJECT (FONT_VARIATIONS, FcTypeString, NULL) + FC_OBJECT (VARIABLE, FcTypeBool, FcCompareBool) +-FC_OBJECT (FONT_HAS_HINT, FcTypeBool, NULL) ++FC_OBJECT (FONT_HAS_HINT, FcTypeBool, FcCompareBool) + /* ^-------------- Add new objects here. */ +-- +2.22.0 + diff --git a/fontconfig-sysroot.patch b/fontconfig-sysroot.patch new file mode 100644 index 0000000..9505f97 --- /dev/null +++ b/fontconfig-sysroot.patch @@ -0,0 +1,285 @@ +From cd51cb241aad7b362b793200ca7d42595c14f52b Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Mon, 21 Oct 2019 16:17:42 +0900 +Subject: [PATCH] Take effect sysroot functionality to the default config file + +When loading the default config file with FONTCONFIG_SYSROOT, +it fails if no /etc/fonts/fonts.conf is available, even if it is +there where is based on sysroot. + +To address this, FcConfig is required to determine the sysroot. +therefore, this change makes FcConfigFilename() deprecated, +use FcConfigGetFilename() instead. + +Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/181 +--- + doc/fcconfig.fncs | 11 +++++++ + fontconfig/fontconfig.h | 4 +++ + src/fccfg.c | 67 ++++++++++++++++++++++++++++------------- + src/fcxml.c | 24 ++++++++++++--- + 4 files changed, 81 insertions(+), 25 deletions(-) + +diff --git a/doc/fcconfig.fncs b/doc/fcconfig.fncs +index 5f1ef43..82769d5 100644 +--- a/doc/fcconfig.fncs ++++ b/doc/fcconfig.fncs +@@ -344,6 +344,15 @@ to be up to date, and used. + @TYPE1@ const FcChar8 * @ARG1@ name + @PURPOSE@ Find a config file + @DESC@ ++This function is deprecated and is replaced by FcConfigGetFilename. ++@@ ++ ++@RET@ FcChar8 * ++@FUNC@ FcConfigGetFilename ++@TYPE1@ FcConfig * @ARG1@ config ++@TYPE2@ const FcChar8 * @ARG2@ name ++@PURPOSE@ Find a config file ++@DESC@ + Given the specified external entity name, return the associated filename. + This provides applications a way to convert various configuration file + references into filename form. +@@ -355,6 +364,8 @@ refers to a file in the current users home directory. Otherwise if the name + doesn't start with '/', it refers to a file in the default configuration + directory; the built-in default directory can be overridden with the + FONTCONFIG_PATH environment variable. ++ ++The result of this function is affected by the FONTCONFIG_SYSROOT environment variable or equivalent functionality. + @@ + + @RET@ FcBool +diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h +index 9586616..2f0e8cf 100644 +--- a/fontconfig/fontconfig.h ++++ b/fontconfig/fontconfig.h +@@ -393,6 +393,10 @@ FcConfigHome (void); + FcPublic FcBool + FcConfigEnableHome (FcBool enable); + ++FcPublic FcChar8 * ++FcConfigGetFilename (FcConfig *config, ++ const FcChar8 *url); ++ + FcPublic FcChar8 * + FcConfigFilename (const FcChar8 *url); + +diff --git a/src/fccfg.c b/src/fccfg.c +index e81eeba..21ccd25 100644 +--- a/src/fccfg.c ++++ b/src/fccfg.c +@@ -686,7 +686,7 @@ FcConfigAddConfigFile (FcConfig *config, + const FcChar8 *f) + { + FcBool ret; +- FcChar8 *file = FcConfigFilename (f); ++ FcChar8 *file = FcConfigGetFilename (config, f); + + if (!file) + return FcFalse; +@@ -2284,10 +2284,19 @@ FcConfigEnableHome (FcBool enable) + } + + FcChar8 * +-FcConfigFilename (const FcChar8 *url) ++FcConfigGetFilename (FcConfig *config, ++ const FcChar8 *url) + { + FcChar8 *file, *dir, **path, **p; ++ const FcChar8 *sysroot; + ++ if (!config) ++ { ++ config = FcConfigGetCurrent (); ++ if (!config) ++ return NULL; ++ } ++ sysroot = FcConfigGetSysRoot (config); + if (!url || !*url) + { + url = (FcChar8 *) getenv ("FONTCONFIG_FILE"); +@@ -2297,13 +2306,23 @@ FcConfigFilename (const FcChar8 *url) + file = 0; + + if (FcStrIsAbsoluteFilename(url)) +- return FcConfigFileExists (0, url); ++ return FcConfigFileExists (sysroot, url); + + if (*url == '~') + { + dir = FcConfigHome (); + if (dir) +- file = FcConfigFileExists (dir, url + 1); ++ { ++ FcChar8 *s; ++ ++ if (sysroot) ++ s = FcStrBuildFilename (sysroot, dir, NULL); ++ else ++ s = dir; ++ file = FcConfigFileExists (s, url + 1); ++ if (sysroot) ++ FcStrFree (s); ++ } + else + file = 0; + } +@@ -2314,7 +2333,15 @@ FcConfigFilename (const FcChar8 *url) + return NULL; + for (p = path; *p; p++) + { +- file = FcConfigFileExists (*p, url); ++ FcChar8 *s; ++ ++ if (sysroot) ++ s = FcStrBuildFilename (sysroot, *p, NULL); ++ else ++ s = *p; ++ file = FcConfigFileExists (s, url); ++ if (sysroot) ++ FcStrFree (s); + if (file) + break; + } +@@ -2323,33 +2350,31 @@ FcConfigFilename (const FcChar8 *url) + return file; + } + ++FcChar8 * ++FcConfigFilename (const FcChar8 *url) ++{ ++ return FcConfigGetFilename (NULL, url); ++} ++ + FcChar8 * + FcConfigRealFilename (FcConfig *config, + const FcChar8 *url) + { +- const FcChar8 *sysroot = FcConfigGetSysRoot (config); +- FcChar8 *n = FcConfigFilename (url); +- FcChar8 *nn = NULL; ++ FcChar8 *n = FcConfigGetFilename (config, url); + + if (n) + { + FcChar8 buf[FC_PATH_MAX]; + ssize_t len; + +- if (sysroot) +- nn = FcStrBuildFilename (sysroot, n, NULL); +- else +- nn = FcStrdup (n); +- FcStrFree (n); +- +- if ((len = FcReadLink (nn, buf, sizeof (buf) - 1)) != -1) ++ if ((len = FcReadLink (n, buf, sizeof (buf) - 1)) != -1) + { + buf[len] = 0; + + if (!FcStrIsAbsoluteFilename (buf)) + { +- FcChar8 *dirname = FcStrDirname (nn); +- FcStrFree (nn); ++ FcChar8 *dirname = FcStrDirname (n); ++ FcStrFree (n); + if (!dirname) + return NULL; + +@@ -2358,18 +2383,18 @@ FcConfigRealFilename (FcConfig *config, + if (!path) + return NULL; + +- nn = FcStrCanonFilename (path); ++ n = FcStrCanonFilename (path); + FcStrFree (path); + } + else + { +- FcStrFree (nn); +- nn = FcStrdup (buf); ++ FcStrFree (n); ++ n = FcStrdup (buf); + } + } + } + +- return nn; ++ return n; + } + + /* +diff --git a/src/fcxml.c b/src/fcxml.c +index d9a67f6..a366644 100644 +--- a/src/fcxml.c ++++ b/src/fcxml.c +@@ -2541,7 +2541,7 @@ FcParseInclude (FcConfigParse *parse) + FcChar8 *filename; + static FcBool warn_conf = FcFalse, warn_confd = FcFalse; + +- filename = FcConfigFilename(s); ++ filename = FcConfigGetFilename(parse->config, s); + if (deprecated == FcTrue && + filename != NULL && + userdir != NULL && +@@ -3532,7 +3532,9 @@ _FcConfigParse (FcConfig *config, + FcStrBuf sbuf; + char buf[BUFSIZ]; + FcBool ret = FcFalse, complain_again = complain; ++ FcStrBuf reason; + ++ FcStrBufInit (&reason, NULL, 0); + #ifdef _WIN32 + if (!pGetSystemWindowsDirectory) + { +@@ -3549,12 +3551,20 @@ _FcConfigParse (FcConfig *config, + } + #endif + +- filename = FcConfigFilename (name); ++ filename = FcConfigGetFilename (config, name); + if (!filename) ++ { ++ FcStrBufString (&reason, (FcChar8 *)"No such file: "); ++ FcStrBufString (&reason, name ? name : (FcChar8 *)"(null)"); + goto bail0; ++ } + realfilename = FcConfigRealFilename (config, name); + if (!realfilename) ++ { ++ FcStrBufString (&reason, (FcChar8 *)"No such realfile: "); ++ FcStrBufString (&reason, name ? name : (FcChar8 *)"(null)"); + goto bail0; ++ } + if (FcStrSetMember (config->availConfigFiles, realfilename)) + { + FcStrFree (filename); +@@ -3582,7 +3592,11 @@ _FcConfigParse (FcConfig *config, + + fd = FcOpen ((char *) realfilename, O_RDONLY); + if (fd == -1) ++ { ++ FcStrBufString (&reason, (FcChar8 *)"Unable to open "); ++ FcStrBufString (&reason, realfilename); + goto bail1; ++ } + + do { + len = read (fd, buf, BUFSIZ); +@@ -3623,11 +3637,13 @@ bail0: + if (!ret && complain_again) + { + if (name) +- FcConfigMessage (0, FcSevereError, "Cannot %s config file \"%s\"", load ? "load" : "scan", name); ++ FcConfigMessage (0, FcSevereError, "Cannot %s config file \"%s\": %s", load ? "load" : "scan", name, FcStrBufDoneStatic (&reason)); + else +- FcConfigMessage (0, FcSevereError, "Cannot %s default config file", load ? "load" : "scan"); ++ FcConfigMessage (0, FcSevereError, "Cannot %s default config file: %s", load ? "load" : "scan", FcStrBufDoneStatic (&reason)); ++ FcStrBufDestroy (&reason); + return FcFalse; + } ++ FcStrBufDestroy (&reason); + return ret; + } + +-- +2.24.1 + diff --git a/fontconfig.spec b/fontconfig.spec index 1bc63c7..b8f5847 100644 --- a/fontconfig.spec +++ b/fontconfig.spec @@ -4,43 +4,43 @@ Summary: Font configuration and customization library Name: fontconfig -Version: 2.17.0 -Release: 3%{?dist} +Version: 2.13.92 +Release: 9%{?dist} # src/ftglue.[ch] is in Public Domain # src/fccache.c contains Public Domain code -## https://gitlab.com/fedora/legal/fedora-license-data/-/issues/177 # fc-case/CaseFolding.txt is in the UCD # otherwise MIT -License: HPND AND LicenseRef-Fedora-Public-Domain AND Unicode-DFS-2016 +License: MIT and Public Domain and UCD Source: http://fontconfig.org/release/%{name}-%{version}.tar.xz URL: http://fontconfig.org Source1: 25-no-bitmap-fedora.conf Source2: fc-cache +Source3: FcConfigGetFilename.3 # https://bugzilla.redhat.com/show_bug.cgi?id=140335 Patch0: %{name}-sleep-less.patch +Patch1: %{name}-required-freetype-version.patch +Patch2: %{name}-score-hint-on-match.patch +Patch3: %{name}-fix-1744377.patch Patch4: %{name}-drop-lang-from-pkgkit-format.patch -Patch5: %{name}-disable-network-required-test.patch -Patch6: %{name}-lower-nonlatin-conf.patch -Patch7: %{name}-fix-crash.patch +Patch5: %{name}-sysroot.patch +Patch6: %{name}-read-latest-cache.patch +Patch7: %{name}-mt.patch +Patch8: %{name}-fix-test.patch +Patch9: %{name}-fix-assertion.patch +Patch10: %{name}-0-timestamp-dir-on-sb.patch -BuildRequires: libxml2-devel +BuildRequires: expat-devel BuildRequires: freetype-devel >= %{freetype_version} BuildRequires: fontpackages-devel -BuildRequires: gettext +BuildRequires: autoconf automake libtool gettext BuildRequires: gperf -BuildRequires: docbook-utils docbook-utils-pdf -BuildRequires: meson ninja-build gcc -Requires: fonts-filesystem freetype -# Register DTD system-wide to make validation work by default -# (used by fonts-rpm-macros) -Requires(pre): xml-common -Requires(postun): xml-common +Requires: fontpackages-filesystem freetype PreReq: freetype >= 2.9.1-6 Requires(post): grep coreutils Requires: font(:lang=en) -Suggests: font(notosans) +Suggests: font(dejavusans) %description Fontconfig is designed to locate fonts within the @@ -72,50 +72,30 @@ which is useful for developing applications that uses fontconfig. %prep %autosetup -p1 -# To reduce a maintenance cost of fontconfig-lower-nonlatin-conf.patch -mv conf.d/65-nonlatin.conf conf.d/69-nonlatin.conf +cp %{SOURCE3} $RPM_BUILD_DIR/%{name}-%{version}/doc %build -%meson -Ddoc=disabled -Dcache-build=disabled -Dxml-backend=libxml2 \ - -Dadditional-fonts-dirs=/usr/share/X11/fonts/Type1,/usr/share/X11/fonts/TTF,/usr/local/share/fonts \ - -Dcache-dir=/usr/lib/fontconfig/cache \ - --default-library=shared -%meson_build +# We don't want to rebuild the docs, but we want to install the included ones. +export HASDOCBOOK=no + +autoreconf +%configure --with-add-fonts=/usr/share/X11/fonts/Type1,/usr/share/X11/fonts/TTF,/usr/local/share/fonts \ + --disable-static --with-cache-dir=/usr/lib/fontconfig/cache + +make %{?_smp_mflags} %install -%meson_install +make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" + +find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' install -p -m 0644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/fonts/conf.d ln -s %{_fontconfig_templatedir}/25-unhint-nonlatin.conf $RPM_BUILD_ROOT%{_fontconfig_confdir}/ -# Use implied value to allow the use of conditional conf -rm $RPM_BUILD_ROOT%{_sysconfdir}/fonts/conf.d/10-sub-pixel-*.conf - -# Do not enable bitmap-related conf -rm $RPM_BUILD_ROOT%{_sysconfdir}/fonts/conf.d/70-*bitmaps*.conf - -# Install docs manually -install -d $RPM_BUILD_ROOT%{_mandir}/man1 -install -d $RPM_BUILD_ROOT%{_mandir}/man3 -install -d $RPM_BUILD_ROOT%{_mandir}/man5 -for f in doc/*.1; do - install -p -m 0644 $f $RPM_BUILD_ROOT%{_mandir}/man1 -done -for f in doc/*.3; do - install -p -m 0644 $f $RPM_BUILD_ROOT%{_mandir}/man3 -done -for f in doc/*.5; do - install -p -m 0644 $f $RPM_BUILD_ROOT%{_mandir}/man5 -done -for f in doc/*.txt doc/*.pdf doc/*.html; do - install -p -m 0644 $f . -done - -# adjust the timestamp to avoid conflicts for multilib -touch -r doc/fontconfig-user.sgml fontconfig-user.txt -touch -r doc/fontconfig-user.sgml fontconfig-user.html -touch -r doc/fontconfig-devel.sgml fontconfig-devel.txt -touch -r doc/fontconfig-devel.sgml fontconfig-devel.html +# move installed doc files back to build directory to package them +# in the right place +mv $RPM_BUILD_ROOT%{_docdir}/fontconfig/* . +rmdir $RPM_BUILD_ROOT%{_docdir}/fontconfig/ # rename fc-cache binary mv $RPM_BUILD_ROOT%{_bindir}/fc-cache $RPM_BUILD_ROOT%{_bindir}/fc-cache-%{__isa_bits} @@ -130,7 +110,7 @@ install -p -m 0755 %{SOURCE2} $RPM_BUILD_ROOT%{_bindir}/fc-cache cat %{name}-conf.lang >> %{name}.lang %check -%meson_test +VERBOSE=1 make check %post umask 0022 @@ -153,21 +133,8 @@ HOME=/root /usr/bin/fc-cache -s %transfiletriggerpostun -- /usr/share/fonts /usr/share/X11/fonts/Type1 /usr/share/X11/fonts/TTF /usr/local/share/fonts HOME=/root /usr/bin/fc-cache -s -%posttrans -if [ -e %{_sysconfdir}/xml/catalog ]; then - %{_bindir}/xmlcatalog --noout --add system \ - "urn:fontconfig:fonts.dtd" \ - "file://%{_datadir}/xml/fontconfig/fonts.dtd" \ - %{_sysconfdir}/xml/catalog -fi - -%postun -if [ $1 == 0 ] && [ -e %{_sysconfdir}/xml/catalog ]; then - %{_bindir}/xmlcatalog --noout --del "urn:fontconfig:fonts.dtd" %{_sysconfdir}/xml/catalog -fi - %files -f %{name}.lang -%doc README.md AUTHORS +%doc README AUTHORS %doc fontconfig-user.txt fontconfig-user.html %doc %{_fontconfig_confdir}/README %license COPYING @@ -187,7 +154,6 @@ fi # If you want to do so, you should use local.conf instead. %config %{_fontconfig_masterdir}/fonts.conf %config(noreplace) %{_fontconfig_confdir}/*.conf -%dir /usr/lib/fontconfig %dir /usr/lib/fontconfig/cache %{_mandir}/man1/* %{_mandir}/man5/* @@ -201,168 +167,11 @@ fi %{_datadir}/gettext/its/fontconfig.loc %files devel-doc -%doc fontconfig-devel.txt fontconfig-devel.html +%doc fontconfig-devel.txt fontconfig-devel %changelog -* Wed Jul 23 2025 Fedora Release Engineering - 2.17.0-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Mon Jun 30 2025 Akira TAGOH - 2.17.0-2 -- Backport a patch to fix a crash with Graphite fonts -- Drop 70-*bitmaps*.conf from /etc/fonts/conf.d so far. - Resolves: rhbz#2375426 - -* Fri Jun 27 2025 Akira TAGOH - 2.17.0-1 -- New upstream release. - Resolves: rhbz#2375126 - -* Fri Apr 11 2025 Akira TAGOH - 2.16.2-1 -- New upstream release. - -* Thu Mar 13 2025 Akira TAGOH - 2.16.1-1 -- New upstream release. - -* Mon Jan 27 2025 Akira TAGOH - 2.16.0-2 -- Fix endian detection. - Resolves: rhbz#2341757 - -* Sat Jan 18 2025 Akira TAGOH - 2.16.0-1 -- New upstream release. - Resolves: rhbz#2338618 -- Use meson instead of autotools to build. -- Disable meson test on s390x temporarily. - -* Thu Jan 16 2025 Fedora Release Engineering - 2.15.0-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Thu Aug 1 2024 Akira TAGOH - 2.15.0-8 -- Fix a memory leak and potentially uninitialized values. - -* Wed Jul 17 2024 Fedora Release Engineering - 2.15.0-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Fri Jun 7 2024 Akira TAGOH - 2.15.0-6 -- Own /usr/lib/fontconfig - Resolves: rhbz#2284076 - -* Mon Apr 29 2024 Michael Kuhn - 2.15.0-5 -- Fix emoji fonts being disabled when bitmap fonts were disabled - -* Sat Feb 10 2024 Akira TAGOH - 2.15.0-4 -- Delete .uuid with fc-cache -f. - Resolves: rhbz#1761885 - -* Wed Jan 24 2024 Fedora Release Engineering - 2.15.0-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Fri Jan 19 2024 Fedora Release Engineering - 2.15.0-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Fri Dec 22 2023 Akira TAGOH - 2.15.0-1 -- New upstream release. - Resolves: rhbz#2255623 - -* Thu Aug 17 2023 Akira TAGOH - 2.14.2-5 -- Update 65-nonlatin.conf to 69-nonlatin.conf - This basically provides substitutes for certain languages and is helpful - to determine default behavior though, we have per-package config for similar purpose. - Since 65 is mostly used for default fonts and this config prevents some behavior for - packages named something coming later than "nonlatin" in the alphabetical order. - So moving this to the safer priority. - This would fixes an issue, particularly Lohit Marathi vs Lohit Devanagari after - updating their priorities from 65 to 66. - -* Wed Jul 19 2023 Fedora Release Engineering - 2.14.2-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Fri Jun 16 2023 Akira TAGOH - 2.14.2-3 -- Drop 10-sub-pixel-rgb-for-kde.conf - Resolves: rhbz#2212512 - -* Tue Apr 4 2023 Akira TAGOH - 2.14.2-2 -- Migrated license tag to SPDX. - -* Fri Jan 27 2023 Akira TAGOH - 2.14.2-1 -- New upstream release. - -* Thu Jan 19 2023 Fedora Release Engineering - 2.14.1-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Sat Nov 26 2022 Akira TAGOH - 2.14.1-2 -- Enable RGB stripes layout for sub-pixel rendering on KDE only. - Resolves: rhbz#2137825 - -* Fri Oct 21 2022 Akira TAGOH - 2.14.1-1 -- New upstream release. - -* Wed Sep 28 2022 Akira TAGOH - 2.14.0-3 -- Remap font paths to other place properly. - -* Thu Jul 21 2022 Fedora Release Engineering - 2.14.0-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Thu Mar 31 2022 Akira TAGOH - 2.14.0-1 -- New upstream release. - -* Fri Feb 4 2022 Akira TAGOH - 2.13.96-1 -- New upstream release. -- Fix missing a file in the archive. - Resolves: rhbz#2050478 - -* Tue Feb 1 2022 Akira TAGOH - 2.13.95-1 -- New upstream release. -- Update deps to font(notosans) - https://fedoraproject.org/wiki/Changes/DefaultToNotoFonts - -* Thu Jan 20 2022 Fedora Release Engineering - 2.13.94-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Wed Jul 21 2021 Fedora Release Engineering - 2.13.94-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Tue Jul 20 2021 Akira TAGOH - 2.13.94-2 -- Fix the score calculation on matching for multiple values. -- Enable 11-lcdfilter-default.conf. - Resolves: rhbz#1965684 - -* Tue Jun 29 2021 Akira TAGOH - 2.13.94-1 -- New upstream release. - -* Thu Mar 25 2021 Akira TAGOH - 2.13.93-6 -- Fix postun scriptlet to remove the entry from xml catalog. - -* Tue Jan 26 2021 Fedora Release Engineering - 2.13.93-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Wed Dec 23 2020 Akira TAGOH - 2.13.93-4 -- cherry pick some upstream patches - - Skip leading white space in style. - - Remove abort from FcCompareSize. - - Fix memory leaks - - Check qual and compare for family tests. -- -* Thu Dec 3 2020 Akira TAGOH - 2.13.93-3 -- Add back fullname property at the scan matching phase for the backward compatibility. - Resolves: rhbz#1902881 - -* Mon Nov 30 2020 Akira TAGOH - 2.13.93-2 -- Fix file conflicts. - -* Sat Nov 28 2020 Akira TAGOH - 2.13.93-1 -- New upstream release. - -* Mon Jul 27 2020 Fedora Release Engineering - 2.13.92-12 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Thu Apr 23 2020 Akira TAGOH - 2.13.92-11 -- deal with system caches as always latest on Silverblue. (#1750891) - -* Thu Apr 02 2020 Akira TAGOH - 2.13.92-10 -- Build against libxml2 instead of expat. - -* Sat Mar 28 2020 Nicolas Mailhot - 2.13.92-9 -- Fix DTD declaration and registration so users and Fedora automation can - easily validate new configuration files +* Thu Apr 23 2020 Akira TAGOH - 2.13.92-9 +- deal with system caches as always latest on Silverblue (#1750891) * Mon Mar 23 2020 Akira TAGOH - 2.13.92-8 - Fix assertion in FcCacheFini() again. diff --git a/plans/basic.fmf b/plans/basic.fmf deleted file mode 100644 index c1627f9..0000000 --- a/plans/basic.fmf +++ /dev/null @@ -1,5 +0,0 @@ -summary: Basic smoke test -discover: - how: fmf -execute: - how: tmt diff --git a/sources b/sources index 9a3bb99..7eee036 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (fontconfig-2.17.0.tar.xz) = dd64905c3e0e5c5881df505b8f0bea594bbac5ce145f57aedcd7130978cd285491497198d8f2d6ed26f7b2abb31268dc3ff97aa75ce998b8e57f2d5c75b240b4 +SHA512 (fontconfig-2.13.92.tar.xz) = 3c8c75ac51cb45531aa02654ce6e32e6db2650679531d2c84df00dd38425c27344599484b2625983ec55b1ba7bab3be8464d7eb75286ea3a0e97a361d2ae91d4 diff --git a/tests/basic/main.fmf b/tests/basic/main.fmf deleted file mode 100644 index d6c06ec..0000000 --- a/tests/basic/main.fmf +++ /dev/null @@ -1,3 +0,0 @@ -summary: Concise summary describing what the test does -test: ./test.sh -framework: beakerlib diff --git a/tests/basic/test.sh b/tests/basic/test.sh deleted file mode 100755 index 10de1b4..0000000 --- a/tests/basic/test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k -. /usr/share/beakerlib/beakerlib.sh || exit 1 - -rlJournalStart - rlPhaseStartSetup - rlRun "tmp=\$(mktemp -d)" 0 "Create tmp directory" - rlRun "pushd $tmp" - rlRun "set -o pipefail" - rlPhaseEnd - - rlPhaseStartTest - rlRun "fc-match" 0 "Check fc-match" - rlRun "fc-list" 0 "Check fc-list" - rlRun "fc-scan /usr/share/fonts" 0 "Check fc-scan" - rlPhaseEnd - - rlPhaseStartCleanup - rlRun "popd" - rlRun "rm -r $tmp" 0 "Remove tmp directory" - rlPhaseEnd -rlJournalEnd