fontconfig: Branch 'master'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 src/fccfg.c               |    2 
 test/test-45-generic.json |    9 +++
 test/test-conf.c          |  124 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+), 1 deletion(-)

New commits:
commit ba15d41bdc0f6e949089d71208f8afdc99e1d19b
Author: Ben Wagner <bungeman@xxxxxxxxxxxx>
Date:   Fri Feb 12 14:51:43 2021 -0500

    Fix stack use after scope in FcConfigCompareValue
    
    Discovered by AddressSanitizer. When left_o and right_o are promoted the
    promoted values are placed on the stack in FcValuePromotionBuffer.
    The FcValuePromotionBuffers must then continue to be in scope while
    left_o and right_o point into their content. In 9d4e5d0f the
    FcValuePromotionBuffers were moved into the incorrect scope, leaving
    left_o and right_o pointing into an object whose lifetime has ended.
    This is similar to left and right which appear to have a smaller scope
    but are actually required to be in the larger scope.
    
    Correct this by moving the FcValuePromotionBuffers to the proper scope.
    Leave the left and right FcValues where they are since they are in the
    correct scope already.
    
    This also adds to test-conf the ability to create charset, langset,
    range, and matrix in patterns. This allows for a simple test which fails
    under AddressSanitizer before this change and passes after.

diff --git a/src/fccfg.c b/src/fccfg.c
index 91af959..462c423 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -989,12 +989,12 @@ FcConfigCompareValue (const FcValue	*left_o,
     FcBool	ret = FcFalse;
     FcOp	op = FC_OP_GET_OP (op_);
     int		flags = FC_OP_GET_FLAGS (op_);
+    FcValuePromotionBuffer buf1, buf2;
 
     if (left_o->type != right_o->type)
     {
         left = FcValueCanonicalize(left_o);
         right = FcValueCanonicalize(right_o);
-        FcValuePromotionBuffer buf1, buf2;
         left = FcConfigPromote (left, right, &buf1);
         right = FcConfigPromote (right, left, &buf2);
         left_o = &left;
diff --git a/test/test-45-generic.json b/test/test-45-generic.json
index 665d7c3..fe2374a 100644
--- a/test/test-45-generic.json
+++ b/test/test-45-generic.json
@@ -21,6 +21,15 @@
                 "family": "math",
                 "lang": "und-zmth"
             }
+        },
+        {
+            "method": "match",
+            "query": {
+                "lang": [ "en", "fr" ]
+            },
+            "result": {
+                // Exercise complex value promotion. No ASAN issues.
+            }
         }
     ]
 }
diff --git a/test/test-conf.c b/test/test-conf.c
index 288bb5b..4959f76 100644
--- a/test/test-conf.c
+++ b/test/test-conf.c
@@ -51,6 +51,8 @@ build_pattern (json_object *obj)
     json_object_object_foreachC (obj, iter)
     {
 	FcValue v;
+	FcBool destroy_v = FcFalse;
+	FcMatrix matrix;
 
 	if (json_object_get_type (iter.val) == json_type_boolean)
 	{
@@ -105,12 +107,134 @@ build_pattern (json_object *obj)
 	{
 	    v.type = FcTypeVoid;
 	}
+	else if (json_object_get_type (iter.val) == json_type_array)
+	{
+	    json_object *o;
+	    json_type type;
+	    int i, n;
+
+	    n = json_object_array_length (iter.val);
+	    if (n == 0) {
+		fprintf (stderr, "E: value is an empty array\n");
+		continue;
+	    }
+
+	    o = json_object_array_get_idx (iter.val, 0);
+	    type = json_object_get_type (o);
+	    if (type == json_type_string) {
+		const FcObjectType *fc_o = FcNameGetObjectType (iter.key);
+		if (fc_o && fc_o->type == FcTypeCharSet) {
+		    FcCharSet* cs = FcCharSetCreate ();
+		    if (!cs) {
+			fprintf (stderr, "E: failed to create charset\n");
+			continue;
+		    }
+		    v.type = FcTypeCharSet;
+		    v.u.c = cs;
+		    destroy_v = FcTrue;
+		    for (i = 0; i < n; i++)
+	            {
+			const FcChar8 *src;
+			int len, nchar, wchar;
+			FcBool valid;
+			FcChar32 dst;
+
+			o = json_object_array_get_idx (iter.val, i);
+			type = json_object_get_type (o);
+			if (type != json_type_string) {
+			    fprintf (stderr, "E: charset value not string\n");
+			    FcValueDestroy (v);
+			    continue;
+			}
+			src = (const FcChar8 *) json_object_get_string (o);
+			len = json_object_get_string_len (o);
+			valid = FcUtf8Len (src, len, &nchar, &wchar);
+			if (valid == FcFalse) {
+			    fprintf (stderr, "E: charset entry not well formed\n");
+			    FcValueDestroy (v);
+			    continue;
+			}
+			if (nchar != 1) {
+			    fprintf (stderr, "E: charset entry not not one codepoint\n");
+			    FcValueDestroy (v);
+			    continue;
+			}
+			FcUtf8ToUcs4 (src, &dst, len);
+			if (FcCharSetAddChar (cs, dst) == FcFalse) {
+			    fprintf (stderr, "E: failed to add to charset\n");
+			    FcValueDestroy (v);
+			    continue;
+			}
+		    }
+		} else {
+		    FcLangSet* ls = FcLangSetCreate ();
+		    if (!ls) {
+			fprintf (stderr, "E: failed to create langset\n");
+			continue;
+		    }
+		    v.type = FcTypeLangSet;
+		    v.u.l = ls;
+		    destroy_v = FcTrue;
+		    for (i = 0; i < n; i++)
+	            {
+			o = json_object_array_get_idx (iter.val, i);
+			type = json_object_get_type (o);
+			if (type != json_type_string) {
+			    fprintf (stderr, "E: langset value not string\n");
+			    FcValueDestroy (v);
+			    continue;
+			}
+			if (FcLangSetAdd (ls, (const FcChar8 *)json_object_get_string (o)) == FcFalse) {
+			    fprintf (stderr, "E: failed to add to langset\n");
+			    FcValueDestroy (v);
+			    continue;
+			}
+		    }
+		}
+	    } else if (type == json_type_double || type == json_type_int) {
+		double values[4];
+		if (n != 2 && n != 4) {
+		    fprintf (stderr, "E: array starting with number not range or matrix\n");
+		    continue;
+		}
+		for (i = 0; i < n; i++) {
+		    o = json_object_array_get_idx (iter.val, i);
+		    type = json_object_get_type (o);
+		    if (type != json_type_double && type != json_type_int) {
+			fprintf (stderr, "E: numeric array entry not a number\n");
+			continue;
+		    }
+		    values[i] = json_object_get_double (o);
+		}
+		if (n == 2) {
+		    v.type = FcTypeRange;
+		    v.u.r = FcRangeCreateDouble (values[0], values[1]);
+		    if (!v.u.r) {
+			fprintf (stderr, "E: failed to create range\n");
+			continue;
+		    }
+		    destroy_v = FcTrue;
+		} else {
+		    v.type = FcTypeMatrix;
+		    v.u.m = &matrix;
+		    matrix.xx = values[0];
+		    matrix.xy = values[1];
+		    matrix.yx = values[2];
+		    matrix.yy = values[3];
+		}
+	    } else {
+		fprintf (stderr, "E: array format not recognized\n");
+		continue;
+	    }
+	}
 	else
 	{
 	    fprintf (stderr, "W: unexpected object to build a pattern: (%s %s)", iter.key, json_type_to_name (json_object_get_type (iter.val)));
 	    continue;
 	}
 	FcPatternAdd (pat, iter.key, v, FcTrue);
+	if (destroy_v)
+	    FcValueDestroy (v);
     }
     return pat;
 }
_______________________________________________
Fontconfig mailing list
Fontconfig@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/fontconfig



[Index of Archives]     [Fedora Fonts]     [Fedora Users]     [Fedora Cloud]     [Kernel]     [Fedora Packaging]     [Fedora Desktop]     [PAM]     [Gimp Graphics Editor]     [Yosemite News]

  Powered by Linux