From cec02510f826e9aa484f72cdfcbc32fc4fbe33ac Mon Sep 17 00:00:00 2001 From: Akira TAGOH Date: Wed, 23 Dec 2020 22:12:12 +0900 Subject: [PATCH] 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. - --- fontconfig-fix-fullname-prop.patch | 72 --- fontconfig-hotfix.patch | 772 +++++++++++++++++++++++++++++ fontconfig.spec | 11 +- 3 files changed, 781 insertions(+), 74 deletions(-) delete mode 100644 fontconfig-fix-fullname-prop.patch create mode 100644 fontconfig-hotfix.patch diff --git a/fontconfig-fix-fullname-prop.patch b/fontconfig-fix-fullname-prop.patch deleted file mode 100644 index 2650279..0000000 --- a/fontconfig-fix-fullname-prop.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff --git a/src/fcfreetype.c b/src/fcfreetype.c -index a7809cbb..4b545bf2 100644 ---- a/src/fcfreetype.c -+++ b/src/fcfreetype.c -@@ -1087,6 +1087,8 @@ static const FT_UShort nameid_order[] = { - TT_NAME_ID_WWS_FAMILY, - TT_NAME_ID_TYPOGRAPHIC_FAMILY, - TT_NAME_ID_FONT_FAMILY, -+ TT_NAME_ID_MAC_FULL_NAME, -+ TT_NAME_ID_FULL_NAME, - TT_NAME_ID_WWS_SUBFAMILY, - TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, - TT_NAME_ID_FONT_SUBFAMILY, -@@ -1222,6 +1224,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face face, - int nfamily_lang = 0; - int nstyle = 0; - int nstyle_lang = 0; -+ int nfullname = 0; -+ int nfullname_lang = 0; - unsigned int p, n; - - FcChar8 *style = 0; -@@ -1443,7 +1447,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face face, - * and treat the instance's nameid as FONT_SUBFAMILY. - * Postscript name is automatically handled by FreeType. */ - if (nameid == TT_NAME_ID_WWS_SUBFAMILY || -- nameid == TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY) -+ nameid == TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY || -+ nameid == TT_NAME_ID_FULL_NAME) - continue; - - if (nameid == TT_NAME_ID_FONT_SUBFAMILY) -@@ -1474,6 +1479,20 @@ FcFreeTypeQueryFaceInternal (const FT_Face face, - np = &nfamily; - nlangp = &nfamily_lang; - break; -+ case TT_NAME_ID_MAC_FULL_NAME: -+ case TT_NAME_ID_FULL_NAME: -+ if (variable) -+ break; -+ if (FcDebug () & FC_DBG_SCANV) -+ printf ("found full (n %2d p %d e %d l 0x%04x)", -+ sname.name_id, sname.platform_id, -+ sname.encoding_id, sname.language_id); -+ -+ obj = FC_FULLNAME_OBJECT; -+ objlang = FC_FULLNAMELANG_OBJECT; -+ np = &nfullname; -+ nlangp = &nfullname_lang; -+ break; - case TT_NAME_ID_WWS_SUBFAMILY: - case TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY: - case TT_NAME_ID_FONT_SUBFAMILY: -diff --git a/src/fcopentype.c b/src/fcopentype.c -index 9382a1ba..59cce456 100644 ---- a/src/fcopentype.c -+++ b/src/fcopentype.c -@@ -76,12 +76,14 @@ FcPatternAddFullname (FcPattern *pat) - FcStrBufChar (&sbuf, ' '); - FcStrBufString (&sbuf, style); - } -+ FcPatternObjectDel (pat, FC_FULLNAME_OBJECT); - if (!FcPatternObjectAddString (pat, FC_FULLNAME_OBJECT, FcStrBufDoneStatic (&sbuf))) - { - FcStrBufDestroy (&sbuf); - return FcFalse; - } - FcStrBufDestroy (&sbuf); -+ FcPatternObjectDel (pat, FC_FULLNAMELANG_OBJECT); - if (!FcPatternObjectAddString (pat, FC_FULLNAMELANG_OBJECT, (const FcChar8 *) "en")) - return FcFalse; - } diff --git a/fontconfig-hotfix.patch b/fontconfig-hotfix.patch new file mode 100644 index 0000000..e506fde --- /dev/null +++ b/fontconfig-hotfix.patch @@ -0,0 +1,772 @@ +From 93c93689f5da4ceaa675e006df63283e25b91d49 Mon Sep 17 00:00:00 2001 +From: Akira TAGOH +Date: Fri, 4 Dec 2020 18:18:03 +0900 +Subject: [PATCH 01/12] Add back fullname property at scan matching phase + +There seems to be a lot of config files using fullname property in the world. +To keep the backward compatibility, fullname property is back to a cache at +the scan matching phase but will be rebuilt once it is done according to family +and style property in the pattern no matter what changes one made in fullname +property during that. + +Ref. https://bugzilla.redhat.com/show_bug.cgi?id=1902881 +--- + src/fcfreetype.c | 21 ++++++++++++++++++++- + src/fcopentype.c | 2 ++ + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/src/fcfreetype.c b/src/fcfreetype.c +index a7809cb..4b545bf 100644 +--- a/src/fcfreetype.c ++++ b/src/fcfreetype.c +@@ -1087,6 +1087,8 @@ static const FT_UShort nameid_order[] = { + TT_NAME_ID_WWS_FAMILY, + TT_NAME_ID_TYPOGRAPHIC_FAMILY, + TT_NAME_ID_FONT_FAMILY, ++ TT_NAME_ID_MAC_FULL_NAME, ++ TT_NAME_ID_FULL_NAME, + TT_NAME_ID_WWS_SUBFAMILY, + TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, + TT_NAME_ID_FONT_SUBFAMILY, +@@ -1222,6 +1224,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face face, + int nfamily_lang = 0; + int nstyle = 0; + int nstyle_lang = 0; ++ int nfullname = 0; ++ int nfullname_lang = 0; + unsigned int p, n; + + FcChar8 *style = 0; +@@ -1443,7 +1447,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face face, + * and treat the instance's nameid as FONT_SUBFAMILY. + * Postscript name is automatically handled by FreeType. */ + if (nameid == TT_NAME_ID_WWS_SUBFAMILY || +- nameid == TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY) ++ nameid == TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY || ++ nameid == TT_NAME_ID_FULL_NAME) + continue; + + if (nameid == TT_NAME_ID_FONT_SUBFAMILY) +@@ -1474,6 +1479,20 @@ FcFreeTypeQueryFaceInternal (const FT_Face face, + np = &nfamily; + nlangp = &nfamily_lang; + break; ++ case TT_NAME_ID_MAC_FULL_NAME: ++ case TT_NAME_ID_FULL_NAME: ++ if (variable) ++ break; ++ if (FcDebug () & FC_DBG_SCANV) ++ printf ("found full (n %2d p %d e %d l 0x%04x)", ++ sname.name_id, sname.platform_id, ++ sname.encoding_id, sname.language_id); ++ ++ obj = FC_FULLNAME_OBJECT; ++ objlang = FC_FULLNAMELANG_OBJECT; ++ np = &nfullname; ++ nlangp = &nfullname_lang; ++ break; + case TT_NAME_ID_WWS_SUBFAMILY: + case TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY: + case TT_NAME_ID_FONT_SUBFAMILY: +diff --git a/src/fcopentype.c b/src/fcopentype.c +index 9382a1b..59cce45 100644 +--- a/src/fcopentype.c ++++ b/src/fcopentype.c +@@ -76,12 +76,14 @@ FcPatternAddFullname (FcPattern *pat) + FcStrBufChar (&sbuf, ' '); + FcStrBufString (&sbuf, style); + } ++ FcPatternObjectDel (pat, FC_FULLNAME_OBJECT); + if (!FcPatternObjectAddString (pat, FC_FULLNAME_OBJECT, FcStrBufDoneStatic (&sbuf))) + { + FcStrBufDestroy (&sbuf); + return FcFalse; + } + FcStrBufDestroy (&sbuf); ++ FcPatternObjectDel (pat, FC_FULLNAMELANG_OBJECT); + if (!FcPatternObjectAddString (pat, FC_FULLNAMELANG_OBJECT, (const FcChar8 *) "en")) + return FcFalse; + } +-- +2.29.2 + +From 3d6926380dc3c8597dc2fd9d34087da9b39dfdd9 Mon Sep 17 00:00:00 2001 +From: Ben Wagner +Date: Fri, 4 Dec 2020 15:00:08 -0500 +Subject: [PATCH 02/12] Skip leading whitespace in style name. + +Found by Clang-Tidy. The intent seems to have been to skip all leading +whitespace in the 'style' string, but instead this loop was an odd +looking no-op. Remove the 'break' from the loop so that it will +continue until end of string or a non-space character is found. +--- + src/fcopentype.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/fcopentype.c b/src/fcopentype.c +index 59cce45..39c05e9 100644 +--- a/src/fcopentype.c ++++ b/src/fcopentype.c +@@ -66,8 +66,7 @@ FcPatternAddFullname (FcPattern *pat) + if (FcPatternObjectGetString (pat, FC_STYLE_OBJECT, n, &style) != FcResultMatch) + return FcFalse; + len = strlen ((const char *) style); +- for (i = 0; style[i] != 0 && isspace (style[i]); i++) +- break; ++ for (i = 0; style[i] != 0 && isspace (style[i]); i++); + memcpy (style, &style[i], len - i); + FcStrBufInit (&sbuf, NULL, 0); + FcStrBufString (&sbuf, family); +-- +2.29.2 + +From 97d541855429629f40a0accdd2b06b7dce7ba2db Mon Sep 17 00:00:00 2001 +From: Ben Wagner +Date: Fri, 4 Dec 2020 15:42:28 -0500 +Subject: [PATCH 03/12] Remove abort from FcCompareSize. + +There doesn't appear to be a good reason to abort when 'v1' has type +FcTypeRange. If there does turn out to be a good reason for this then it +should be better documented and the code for handling this case removed. +At worst it seems -1 should be returned as it is for other unknown +types. It is possible this is left over debug code from the initial +implementation. +--- + src/fcmatch.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/fcmatch.c b/src/fcmatch.c +index df6db71..53c3b0e 100644 +--- a/src/fcmatch.c ++++ b/src/fcmatch.c +@@ -235,7 +235,6 @@ FcCompareSize (const FcValue *v1, const FcValue *v2, FcValue *bestValue) + b1 = e1 = value1.u.d; + break; + case FcTypeRange: +- abort(); + b1 = value1.u.r->begin; + e1 = value1.u.r->end; + break; +-- +2.29.2 + +From d55eaa6b3148691f32ec19c5c36dfc8818a6385f Mon Sep 17 00:00:00 2001 +From: Ben Wagner +Date: Fri, 11 Dec 2020 11:54:43 -0500 +Subject: [PATCH 07/12] Fix leaks in fcxml.c, fc-match.c, and tests. + +Fix leaks reported by AddressSanitizer when running 'make check'. +--- + fc-match/fc-match.c | 8 +++++++- + src/fcxml.c | 4 +++- + test/test-bz106632.c | 8 ++++++++ + test/test-issue180.c | 4 +++- + 4 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/fc-match/fc-match.c b/fc-match/fc-match.c +index 4362ec1..f31047e 100644 +--- a/fc-match/fc-match.c ++++ b/fc-match/fc-match.c +@@ -117,6 +117,7 @@ main (int argc, char **argv) + int brief = 0; + int sort = 0, all = 0; + const FcChar8 *format = NULL; ++ const FcChar8 *format_optarg = NULL; + int i; + FcObjectSet *os = 0; + FcFontSet *fs; +@@ -146,7 +147,7 @@ main (int argc, char **argv) + brief = 1; + break; + case 'f': +- format = (FcChar8 *) strdup (optarg); ++ format = format_optarg = (FcChar8 *) strdup (optarg); + break; + case 'V': + fprintf (stderr, "fontconfig version %d.%d.%d\n", +@@ -269,5 +270,10 @@ main (int argc, char **argv) + + FcFini (); + ++ if (format_optarg) { ++ free ((void*)format_optarg); ++ format_optarg = NULL; ++ } ++ + return 0; + } +diff --git a/src/fcxml.c b/src/fcxml.c +index 3f22581..9efe157 100644 +--- a/src/fcxml.c ++++ b/src/fcxml.c +@@ -2307,7 +2307,9 @@ FcParseCacheDir (FcConfigParse *parse) + if (data[0] == 0) + { + FcConfigMessage (parse, FcSevereWarning, "empty cache directory name ignored"); +- return; ++ FcStrFree (data); ++ data = prefix; ++ goto bail; + } + if (prefix) + { +diff --git a/test/test-bz106632.c b/test/test-bz106632.c +index 0f37b9c..c610d73 100644 +--- a/test/test-bz106632.c ++++ b/test/test-bz106632.c +@@ -221,6 +221,7 @@ main (void) + ret = 1; + goto bail; + } ++ FcFontSetDestroy (fs); + fprintf (stderr, "D: Removing %s\n", fontdir); + snprintf (cmd, 512, "sleep 1; rm -f %s%s*; sleep 1", fontdir, FC_DIR_SEPARATOR_S); + (void) system (cmd); +@@ -243,6 +244,8 @@ main (void) + ret = 3; + goto bail; + } ++ FcConfigDestroy (config); ++ + config = FcConfigCreate (); + if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, FcTrue)) + { +@@ -266,6 +269,7 @@ main (void) + ret = 1; + goto bail; + } ++ FcFontSetDestroy (fs); + fprintf (stderr, "D: Copying %s to %s\n", FONTFILE, fontdir); + snprintf (cmd, 512, "sleep 1; cp -a %s %s; sleep 1", FONTFILE, fontdir); + (void) system (cmd); +@@ -288,6 +292,8 @@ main (void) + ret = 3; + goto bail; + } ++ FcConfigDestroy (config); ++ + config = FcConfigCreate (); + if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, FcTrue)) + { +@@ -311,6 +317,8 @@ main (void) + ret = 1; + goto bail; + } ++ FcFontSetDestroy (fs); ++ FcConfigDestroy (config); + + bail: + fprintf (stderr, "Cleaning up\n"); +diff --git a/test/test-issue180.c b/test/test-issue180.c +index 2832d3b..9d0795e 100644 +--- a/test/test-issue180.c ++++ b/test/test-issue180.c +@@ -53,7 +53,9 @@ main (void) + fprintf (stderr, "There was one or more cachedirs\n"); + return 1; + } ++ FcStrListDone (l); + FcConfigDestroy (cfg); ++ + cfg = FcConfigCreate (); + if (!FcConfigParseAndLoadFromMemory (cfg, doc2, FcTrue)) + { +@@ -66,7 +68,7 @@ main (void) + fprintf (stderr, "There was one or more cachedirs (with prefix)\n"); + return 1; + } +- ++ FcStrListDone (l); + FcConfigDestroy (cfg); + + return 0; +-- +2.29.2 + +From 5cd11d19dfb2d901e1f6b690ae504d3bf5f5ff69 Mon Sep 17 00:00:00 2001 +From: Ben Wagner +Date: Thu, 10 Dec 2020 14:12:05 -0500 +Subject: [PATCH 08/12] Fix wild frees and leak of fs in test-conf. + +Reported by AddressSanitizer when running test-conf. The `query`, +`result`, and `result_fs` were not initialized to NULL so could result +in a wild free when first initialized. + +The `method` was also not initialized to NULL so comparisons could be +made against random data if it had not yet been assigned. + +The outer `fs` was never destroyed, but is also not used, so remove. +--- + test/test-conf.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/test/test-conf.c b/test/test-conf.c +index d4de21a..6097983 100644 +--- a/test/test-conf.c ++++ b/test/test-conf.c +@@ -158,7 +158,6 @@ static FcBool + run_test (FcConfig *config, json_object *root) + { + json_object *tests; +- FcFontSet *fs; + int i, n, fail = 0; + + if (!json_object_object_get_ex (root, "tests", &tests) || +@@ -167,15 +166,15 @@ run_test (FcConfig *config, json_object *root) + fprintf (stderr, "W: No test cases defined\n"); + return FcFalse; + } +- fs = FcFontSetCreate (); + n = json_object_array_length (tests); + for (i = 0; i < n; i++) + { + json_object *obj = json_object_array_get_idx (tests, i); + json_object_iter iter; +- FcPattern *query, *result; +- FcFontSet *result_fs; +- const char *method; ++ FcPattern *query = NULL; ++ FcPattern *result = NULL; ++ FcFontSet *result_fs = NULL; ++ const char *method = NULL; + + if (json_object_get_type (obj) != json_type_object) + continue; +-- +2.29.2 + +From b35c72dbc7da5b61a84766cfa431c95c1d1b35bd Mon Sep 17 00:00:00 2001 +From: Ben Wagner +Date: Tue, 15 Dec 2020 17:39:05 -0500 +Subject: [PATCH 09/12] Always run-test-conf, but skip if not built. + +The test-conf test requires libjson-c to be available in order to be +built. However, there has been no user indication that additional tests +could be built if the json-c development files were available. + +Continue to not build test-conf if json-c is not available, but do run +the test harness. The test harness is updated to SKIP the test if the +test-conf binary is unavailable. +--- + test/Makefile.am | 2 +- + test/run-test-conf.sh | 6 ++++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/test/Makefile.am b/test/Makefile.am +index 5a998b3..1a9b293 100644 +--- a/test/Makefile.am ++++ b/test/Makefile.am +@@ -101,8 +101,8 @@ if ENABLE_JSONC + check_PROGRAMS += test-conf + test_conf_CFLAGS = $(JSONC_CFLAGS) + test_conf_LDADD = $(top_builddir)/src/libfontconfig.la $(JSONC_LIBS) +-TESTS += run-test-conf.sh + endif ++TESTS += run-test-conf.sh + + check_PROGRAMS += test-bz106618 + test_bz106618_LDADD = $(top_builddir)/src/libfontconfig.la +diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh +index 437bafa..e085e82 100644 +--- a/test/run-test-conf.sh ++++ b/test/run-test-conf.sh +@@ -33,6 +33,12 @@ BUILDTESTDIR=${builddir-"$MyPWD"} + + RUNNER=../test/test-conf$EXEEXT + ++if [ ! -f ${RUNNER} ]; then ++ echo "${RUNNER} not found!\n" ++ echo "Building this test requires libjson-c development files to be available." ++ exit 77 # SKIP ++fi ++ + for i in \ + 60-generic.conf \ + 90-synthetic.conf \ +-- +2.29.2 + +From 921ede9f460fb661146182809557a1da2dd7afd7 Mon Sep 17 00:00:00 2001 +From: Ben Wagner +Date: Tue, 15 Dec 2020 16:30:14 -0500 +Subject: [PATCH 10/12] Fix test-conf string to integer conversion. + +The test-conf build_pattern attempted to convert known constant strings +into integer values. However, it did so by always converting the string +value to an integer if possible and then complaining if the key wasn't +of the expected type. This lead to error messages on "style": "Regular" +since "Regular" was recognized as "weight". + +Instead, only attempt conversion from string to integer if the key is +the name of an object which can take an integer type. This eliminates +the spurious non-fatal errors reported when parsing +test-90-synthetic.json. + +This also fixes an issue where the created value was given the type of +the object found, but the integer field was assigned. Instead, check +that the object type can take an integer and always set the value type +to integer. +--- + test/test-conf.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/test/test-conf.c b/test/test-conf.c +index 6097983..288bb5b 100644 +--- a/test/test-conf.c ++++ b/test/test-conf.c +@@ -69,22 +69,25 @@ build_pattern (json_object *obj) + } + else if (json_object_get_type (iter.val) == json_type_string) + { +- const FcConstant *c = FcNameGetConstant ((const FcChar8 *) json_object_get_string (iter.val)); +- FcBool b; +- +- if (c) ++ const FcObjectType *o = FcNameGetObjectType (iter.key); ++ if (o && (o->type == FcTypeRange || o->type == FcTypeDouble || o->type == FcTypeInteger)) + { +- const FcObjectType *o; +- ++ const FcConstant *c = FcNameGetConstant ((const FcChar8 *) json_object_get_string (iter.val)); ++ if (!c) { ++ fprintf (stderr, "E: value is not a known constant\n"); ++ fprintf (stderr, " key: %s\n", iter.key); ++ fprintf (stderr, " val: %s\n", json_object_get_string (iter.val)); ++ continue; ++ } + if (strcmp (c->object, iter.key) != 0) + { +- fprintf (stderr, "E: invalid object type for const\n"); +- fprintf (stderr, " actual result: %s\n", iter.key); +- fprintf (stderr, " expected result: %s\n", c->object); ++ fprintf (stderr, "E: value is a constant of different object\n"); ++ fprintf (stderr, " key: %s\n", iter.key); ++ fprintf (stderr, " val: %s\n", json_object_get_string (iter.val)); ++ fprintf (stderr, " key implied by value: %s\n", c->object); + continue; + } +- o = FcNameGetObjectType (c->object); +- v.type = o->type; ++ v.type = FcTypeInteger; + v.u.i = c->value; + } + else if (strcmp (json_object_get_string (iter.val), "DontCare") == 0) +-- +2.29.2 + +From df29933e1a06b7aa7af229bd7cd03c62d957f15f Mon Sep 17 00:00:00 2001 +From: Szunti +Date: Sun, 6 Dec 2020 12:52:44 +0100 +Subject: [PATCH 11/12] Check qual and compare for family tests + +Fixes #267. Hash table lookups assumed qual="any" compare="eq". +Add a test too. +--- + src/fccfg.c | 16 ++- + test/Makefile.am | 4 + + test/meson.build | 1 + + test/test-family-matching.c | 228 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 248 insertions(+), 1 deletion(-) + create mode 100644 test/test-family-matching.c + +diff --git a/src/fccfg.c b/src/fccfg.c +index 7b857bf..00a94e5 100644 +--- a/src/fccfg.c ++++ b/src/fccfg.c +@@ -1714,6 +1714,7 @@ FcConfigMatchValueList (FcPattern *p, + FcExpr *e = t->expr; + FcValue value; + FcValueList *v; ++ FcOp op; + + while (e) + { +@@ -1731,10 +1732,23 @@ FcConfigMatchValueList (FcPattern *p, + + if (t->object == FC_FAMILY_OBJECT && table) + { +- if (!FamilyTableLookup (table, t->op, FcValueString (&value))) ++ op = FC_OP_GET_OP (t->op); ++ if (op == FcOpEqual || op == FcOpListing) + { ++ if (!FamilyTableLookup (table, t->op, FcValueString (&value))) ++ { + ret = 0; + goto done; ++ } ++ } ++ if (op == FcOpNotEqual && t->qual == FcQualAll) ++ { ++ ret = 0; ++ if (!FamilyTableLookup (table, t->op, FcValueString (&value))) ++ { ++ ret = values; ++ } ++ goto done; + } + } + for (v = values; v; v = FcValueListNext(v)) +diff --git a/test/Makefile.am b/test/Makefile.am +index 1a9b293..30d8c2a 100644 +--- a/test/Makefile.am ++++ b/test/Makefile.am +@@ -167,6 +167,10 @@ check_PROGRAMS += test-issue180 + test_issue180_LDADD = $(top_builddir)/src/libfontconfig.la + TESTS += test-issue180 + ++check_PROGRAMS += test-family-matching ++test_family_matching_LDADD = $(top_builddir)/src/libfontconfig.la ++TESTS += test-family-matching ++ + EXTRA_DIST=run-test.sh run-test-conf.sh $(LOG_COMPILER) $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names + + CLEANFILES = \ +diff --git a/test/meson.build b/test/meson.build +index 96b30a9..59de427 100644 +--- a/test/meson.build ++++ b/test/meson.build +@@ -6,6 +6,7 @@ tests = [ + ['test-bz106618.c'], + ['test-bz1744377.c'], + ['test-issue180.c'], ++ ['test-family-matching.c'], + ] + + if host_machine.system() != 'windows' +diff --git a/test/test-family-matching.c b/test/test-family-matching.c +new file mode 100644 +index 0000000..9fab36c +--- /dev/null ++++ b/test/test-family-matching.c +@@ -0,0 +1,228 @@ ++/* ++ * fontconfig/test/test-family-matching.c ++ * ++ * Copyright © 2020 Zoltan Vandrus ++ * ++ * 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 ++ ++#define FC_TEST_RESULT "testresult" ++ ++typedef enum _TestMatchResult { ++ TestMatch, ++ TestNoMatch, ++ TestMatchError ++} TestMatchResult; ++ ++typedef enum _TestResult { ++ TestPassed, ++ TestFailed, ++ TestError ++} TestResult; ++ ++static TestMatchResult ++TestMatchPattern (const char *test, FcPattern *p) ++{ ++ const FcChar8 *xml_pre = (const FcChar8 *) "" ++ "\n" ++ " \n" ++ ""; ++ ++ const FcChar8 *xml_post = (const FcChar8 *) "" ++ " \n" ++ " true\n" ++ " \n" ++ " \n" ++ "\n" ++ ""; ++ ++ FcChar8 *xml, *concat; ++ FcConfig *cfg; ++ FcResult result; ++ FcBool dummy; ++ TestResult ret = TestMatchError; ++ ++ FcPattern *pat = FcPatternDuplicate (p); ++ if (!pat) ++ { ++ fprintf (stderr, "Unable to duplicate pattern.\n"); ++ goto bail0; ++ } ++ ++ concat = FcStrPlus (xml_pre, (const FcChar8 *) test); ++ if (!concat) ++ { ++ fprintf (stderr, "Concatenation failed.\n"); ++ goto bail0; ++ } ++ ++ xml = FcStrPlus (concat, xml_post); ++ FcStrFree (concat); ++ if (!xml) ++ { ++ fprintf (stderr, "Concatenation failed.\n"); ++ goto bail0; ++ } ++ ++ cfg = FcConfigCreate (); ++ if (!cfg) ++ { ++ fprintf (stderr, "Unable to create a new empty config.\n"); ++ return TestMatchError; ++ } ++ ++ if (!FcConfigParseAndLoadFromMemory (cfg, xml, FcTrue)) ++ { ++ fprintf (stderr, "Unable to load a config from memory.\n"); ++ goto bail1; ++ } ++ ++ if (!FcConfigSubstitute (cfg, pat, FcMatchPattern)) ++ { ++ fprintf (stderr, "Unable to substitute config.\n"); ++ goto bail1; ++ } ++ ++ result = FcPatternGetBool (pat, FC_TEST_RESULT, 0, &dummy); ++ switch (result) { ++ case FcResultMatch: ++ ret = TestMatch; ++ break; ++ case FcResultNoMatch: ++ ret = TestNoMatch; ++ break; ++ default: ++ fprintf (stderr, "Unable to check pattern.\n"); ++ break; ++ } ++ ++bail1: ++ FcConfigDestroy (cfg); ++bail0: ++ FcPatternDestroy (pat); ++ return ret; ++} ++ ++static TestResult ++TestShouldMatchPattern(const char* test, FcPattern *pat, int negate) ++{ ++ switch (TestMatchPattern (test, pat)) { ++ case TestMatch: ++ if (!negate) { ++ return TestPassed; ++ } ++ else ++ { ++ printf ("Following test unexpectedly matched:\n%s", test); ++ printf ("on\n"); ++ FcPatternPrint (pat); ++ return TestFailed; ++ } ++ break; ++ case TestNoMatch: ++ if (!negate) { ++ printf ("Following test should have matched:\n%s", test); ++ printf ("on\n"); ++ FcPatternPrint (pat); ++ return TestFailed; ++ } ++ else ++ { ++ return TestPassed; ++ } ++ break; ++ case TestMatchError: ++ return TestError; ++ break; ++ default: ++ fprintf (stderr, "This shouldn't have been reached.\n"); ++ return TestError; ++ } ++} ++ ++#define MAX(a,b) ((a) > (b) ? (a) : (b)) ++ ++static TestResult ++UpdateResult (TestResult* res, TestResult resNew) ++{ ++ *res = MAX(*res, resNew); ++ return *res; ++} ++ ++static TestResult ++TestFamily (void) ++{ ++ const char *test; ++ TestResult res = TestPassed; ++ ++ FcPattern *pat = FcPatternBuild (NULL, ++ FC_FAMILY, FcTypeString, "family1", ++ FC_FAMILY, FcTypeString, "family2", ++ FC_FAMILY, FcTypeString, "family3", ++ NULL); ++ ++ if (!pat) ++ { ++ fprintf (stderr, "Unable to build pattern.\n"); ++ return TestError; ++ } ++ ++ #define SHOULD_MATCH(p,t) \ ++ UpdateResult (&res, TestShouldMatchPattern (t, p, 0)) ++ #define SHOULD_NOT_MATCH(p,t) \ ++ UpdateResult (&res, TestShouldMatchPattern (t, p, 1)) ++ ++ test = "\n" ++ " foo\n" ++ "\n" ++ ""; ++ SHOULD_MATCH(pat, test); ++ ++ test = "" ++ "\n" ++ " family2\n" ++ "\n" ++ ""; ++ SHOULD_NOT_MATCH(pat, test); ++ ++ test = "" ++ "\n" ++ " family3\n" ++ "\n" ++ ""; ++ SHOULD_MATCH(pat, test); ++ ++ test = "" ++ "\n" ++ " foo\n" ++ "\n" ++ ""; ++ SHOULD_NOT_MATCH(pat, test); ++ ++ return res; ++} ++ ++int ++main (void) ++{ ++ return (TestFamily ()); ++} +-- +2.29.2 + diff --git a/fontconfig.spec b/fontconfig.spec index 42bd073..9928dc6 100644 --- a/fontconfig.spec +++ b/fontconfig.spec @@ -5,7 +5,7 @@ Summary: Font configuration and customization library Name: fontconfig Version: 2.13.93 -Release: 3%{?dist} +Release: 4%{?dist} # src/ftglue.[ch] is in Public Domain # src/fccache.c contains Public Domain code # fc-case/CaseFolding.txt is in the UCD @@ -20,7 +20,7 @@ Source2: fc-cache Patch0: %{name}-sleep-less.patch Patch4: %{name}-drop-lang-from-pkgkit-format.patch Patch5: %{name}-disable-network-required-test.patch -Patch6: %{name}-fix-fullname-prop.patch +Patch6: %{name}-hotfix.patch BuildRequires: libxml2-devel BuildRequires: freetype-devel >= %{freetype_version} @@ -188,6 +188,13 @@ fi %doc fontconfig-devel.txt fontconfig-devel %changelog +* 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