From fa6c6b53c5a42ae6a9f8254ca9603dbe0aec63ad Mon Sep 17 00:00:00 2001 From: Akira TAGOH Date: Fri, 22 May 2015 16:53:34 +0900 Subject: [PATCH] Fix memory leaks after FcFini() Reported by Jia Wang https://bugs.freedesktop.org/show_bug.cgi?id=83770 --- fontconfig/fontconfig.h | 2 +- src/fcinit.c | 2 ++ src/fcint.h | 6 ++++++ src/fcobjs.c | 25 +++++++++++++++++++++- src/fcxml.c | 47 +++++++++++++++++++++++++++++++++++++---- 5 files changed, 76 insertions(+), 6 deletions(-) diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index 60496d9..65b85ae 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -217,7 +217,7 @@ typedef struct _FcMatrix { typedef struct _FcCharSet FcCharSet; typedef struct _FcObjectType { - const char *object; + char *object; FcType type; } FcObjectType; diff --git a/src/fcinit.c b/src/fcinit.c index 0f13ec3..5e7c2f1 100644 --- a/src/fcinit.c +++ b/src/fcinit.c @@ -192,6 +192,8 @@ FcFini (void) FcConfigFini (); FcCacheFini (); FcDefaultFini (); + FcObjectFini (); + FcConfigPathFini (); } /* diff --git a/src/fcint.h b/src/fcint.h index 80205c9..83815f7 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -880,6 +880,9 @@ FcPrivate FcConfig * FcInitLoadOwnConfigAndFonts (FcConfig *config); /* fcxml.c */ +FcPrivate void +FcConfigPathFini (void); + FcPrivate void FcTestDestroy (FcTest *test); @@ -1192,6 +1195,9 @@ FcStrSerialize (FcSerialize *serialize, const FcChar8 *str); /* fcobjs.c */ +FcPrivate void +FcObjectFini (void); + FcPrivate FcObject FcObjectLookupIdByName (const char *str); diff --git a/src/fcobjs.c b/src/fcobjs.c index bad9824..2895dc0 100644 --- a/src/fcobjs.c +++ b/src/fcobjs.c @@ -44,6 +44,26 @@ struct FcObjectOtherTypeInfo { FcObject id; } *other_types; +void +FcObjectFini (void) +{ + struct FcObjectOtherTypeInfo *ots, *ot; + +retry: + ots = fc_atomic_ptr_get (&other_types); + if (!fc_atomic_ptr_cmpexch (&other_types, ots, NULL)) + goto retry; + + while (ots) + { + ot = ots->next; + if (ots->object.object) + free (ots->object.object); + free (ots); + ots = ot; + } +} + static FcObjectType * _FcObjectLookupOtherTypeByName (const char *str, FcObject *id) { @@ -62,13 +82,16 @@ retry: if (!ot) return NULL; - ot->object.object = (const char *) FcStrdup (str); + ot->object.object = (char *) FcStrdup (str); ot->object.type = FcTypeUnknown; ot->id = fc_atomic_int_add (next_id, +1); ot->next = ots; if (!fc_atomic_ptr_cmpexch (&other_types, ots, ot)) { + if (ot->object.object) + free (ot->object.object); free (ot); + fc_atomic_int_add (next_id, -1); goto retry; } } diff --git a/src/fcxml.c b/src/fcxml.c index 9a6f08d..1a68bc4 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -57,6 +57,9 @@ extern FcChar8 fontconfig_instprefix[]; #endif +static FcChar8 *__fc_userdir = NULL; +static FcChar8 *__fc_userconf = NULL; + static void FcExprDestroy (FcExpr *e); @@ -2262,6 +2265,24 @@ FcParseCacheDir (FcConfigParse *parse) FcStrFree (data); } +void +FcConfigPathFini (void) +{ + FcChar8 *s; + +retry_dir: + s = fc_atomic_ptr_get (&__fc_userdir); + if (!fc_atomic_ptr_cmpexch (&__fc_userdir, s, NULL)) + goto retry_dir; + free (s); + +retry_conf: + s = fc_atomic_ptr_get (&__fc_userconf); + if (!fc_atomic_ptr_cmpexch (&__fc_userconf, s, NULL)) + goto retry_conf; + free (s); +} + static void FcParseInclude (FcConfigParse *parse) { @@ -2272,8 +2293,7 @@ FcParseInclude (FcConfigParse *parse) FcBool deprecated = FcFalse; #endif FcChar8 *prefix = NULL, *p; - static FcChar8 *userdir = NULL; - static FcChar8 *userconf = NULL; + FcChar8 userdir, userconf; s = FcStrBufDoneStatic (&parse->pstack->str); if (!s) @@ -2303,6 +2323,7 @@ FcParseInclude (FcConfigParse *parse) { size_t plen = strlen ((const char *)prefix); size_t dlen = strlen ((const char *)s); + FcChar8 *u; p = realloc (prefix, plen + 1 + dlen + 1); if (!p) @@ -2318,14 +2339,32 @@ FcParseInclude (FcConfigParse *parse) if (FcFileIsDir (s)) { userdir: + userdir = fc_atomic_ptr_get (&__fc_userdir); if (!userdir) - userdir = FcStrdup (s); + { + u = FcStrdup (s); + if (!fc_atomic_ptr_cmpexch (&__fc_userdir, userdir, u)) + { + free (u); + goto userdir; + } + userdir = u; + } } else if (FcFileIsFile (s)) { userconf: + userconf = fc_atomic_ptr_get (&__fc_userconf); if (!userconf) - userconf = FcStrdup (s); + { + u = FcStrdup (s); + if (!fc_atomic_ptr_cmpexch (&__fc_userconf, userconf, u)) + { + free (u); + goto userconf; + } + userconf = u; + } } else {