changeset 5818:15b0715c204d

Avoid passing patterns to with charset property to FcNameUnparse. Prevents crash reported by Raymond Toy.
author Stephen J. Turnbull <stephen@xemacs.org>
date Sat, 18 Oct 2014 21:20:42 +0900
parents a58070ee1f31
children ba0ff364bd94
files src/ChangeLog src/font-mgr.c src/font-mgr.h src/fontcolor-x.c src/fontcolor-xlike-inc.c
diffstat 5 files changed, 29 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sun Oct 12 07:17:55 2014 +0200
+++ b/src/ChangeLog	Sat Oct 18 21:20:42 2014 +0900
@@ -1,3 +1,11 @@
+2014-10-18  Stephen J. Turnbull  <stephen@xemacs.org>
+
+	* fontcolor-xlike-inc.c (xft_find_charset_font):
+	* fontcolor-x.c (x_font_instance_truename):
+	* font-mgr.h (PRINT_XFT_PATTERN):
+	* font-mgr.c (Ffc_name_unparse):
+	Protect Ffc_name_unparse from FcNameUnparse crash on charset property.
+
 2014-10-08  Jerry James  <james@xemacs.org>
 
 	* tls.c (init_tls): Remove blatant Fedoraism from the OpenSSL version.
--- a/src/font-mgr.c	Sun Oct 12 07:17:55 2014 +0200
+++ b/src/font-mgr.c	Sat Oct 18 21:20:42 2014 +0900
@@ -255,12 +255,19 @@
    We provide both. */
 DEFUN ("fc-name-unparse", Ffc_name_unparse, 1, 1, 0, /*
 Unparse an fc pattern object to a string.
+  To work around a bug in fontconfig (at least 2.11.1), the 'charset' property
+is removed before passing to FcNameUnparse.  To extract the 'charset' property,
+use `\(fc-pattern-get PATTERN "charset")'.
 */
       (pattern))
 {
   FcChar8 *name;
   Lisp_Object result;
+
   CHECK_FC_PATTERN (pattern);
+  /* #### Could use multiple values here to extract and return charset? */
+  FcPatternDel (XFC_PATTERN_PTR (pattern), FC_CHARSET);
+
   name = FcNameUnparse (XFC_PATTERN_PTR (pattern));
   result = build_fcapi_string (name);
   xfree (name);
@@ -337,6 +344,9 @@
 
 /* Generic interface to FcPatternGet()
  * Don't support the losing symbol-for-property interface.
+ * To support that interface properly, we should have `fc-register-property'
+ * so that only registered symbols could be used.  Then it would serve to
+ * provide the same kind of check that the C-level FC_* macros do.
  */
 DEFUN ("fc-pattern-get", Ffc_pattern_get, 2, 4, 0, /*
 From PATTERN, extract PROPERTY for the ID'th member, of type TYPE.
--- a/src/font-mgr.h	Sun Oct 12 07:17:55 2014 +0200
+++ b/src/font-mgr.h	Sat Oct 18 21:20:42 2014 +0900
@@ -144,8 +144,9 @@
 #define PRINT_XFT_PATTERN(level,format,pattern)			\
   do {								\
     DECLARE_EISTRING (eistrpxft_name);				\
-    Extbyte *name = (Extbyte *) FcNameUnparse (pattern);	\
-								\
+    Extbyte *name;						\
+    FcPatternDel(pattern, FC_CHARSET);				\
+    name = (Extbyte *) FcNameUnparse (pattern);			\
     eicpy_ext(eistrpxft_name,					\
               name ? name : "FONT WITH NULL NAME",		\
               Qfc_font_name_encoding);				\
--- a/src/fontcolor-x.c	Sun Oct 12 07:17:55 2014 +0200
+++ b/src/fontcolor-x.c	Sat Oct 18 21:20:42 2014 +0900
@@ -755,13 +755,16 @@
   if (NILP (FONT_INSTANCE_TRUENAME (f)) && FONT_INSTANCE_X_XFTFONT (f))
     {
       /* The font is already open, we just unparse. */
-      FcChar8 *res = FcNameUnparse (FONT_INSTANCE_X_XFTFONT (f)->pattern);
-      if (! FONT_INSTANCE_X_XFTFONT (f)->pattern)
+      FcPattern* pattern = FONT_INSTANCE_X_XFTFONT (f)->pattern;
+      FcChar8 *res;
+      if (!pattern)
 	{
 	  maybe_signal_error (Qgui_error,
 			      "Xft font present but lacks pattern",
 			      wrap_font_instance(f), Qfont, errb);
 	}
+      FcPatternDel (pattern, FC_CHARSET);  /* FcNameUnparse may choke */
+      res = FcNameUnparse (pattern);
       if (res)
 	{
 	  FONT_INSTANCE_TRUENAME (f) = 
--- a/src/fontcolor-xlike-inc.c	Sun Oct 12 07:17:55 2014 +0200
+++ b/src/fontcolor-xlike-inc.c	Sat Oct 18 21:20:42 2014 +0900
@@ -505,7 +505,9 @@
 	FcPattern *p = FcFontRenderPrepare (fcc, fontxft, fontxft);
 	Extbyte *name;
 
-	/* full name, including language coverage and repertoire */
+	/* full name, including language coverage and repertoire
+	   we delete 'charset' here because FcNameUnparse chokes on it */
+	FcPatternDel (p, FC_CHARSET);
 	name = (Extbyte *) FcNameUnparse (p);
 	eicpy_ext (eistr_fullname,
 		   (name ? name : "NOT FOUND"),
@@ -514,7 +516,6 @@
 
 	/* long name, omitting coverage and repertoire, plus a number
 	   of rarely useful properties */
-	FcPatternDel (p, FC_CHARSET);
 	FcPatternDel (p, FC_LANG);
 #ifdef FC_WIDTH
 	FcPatternDel (p, FC_WIDTH);