Fix memory leaks after FcFini()

Reported by Jia Wang

https://bugs.freedesktop.org/show_bug.cgi?id=83770
This commit is contained in:
Akira TAGOH 2015-05-22 16:53:34 +09:00
parent bcfe167e3d
commit fa6c6b53c5
5 changed files with 76 additions and 6 deletions

View File

@ -217,7 +217,7 @@ typedef struct _FcMatrix {
typedef struct _FcCharSet FcCharSet; typedef struct _FcCharSet FcCharSet;
typedef struct _FcObjectType { typedef struct _FcObjectType {
const char *object; char *object;
FcType type; FcType type;
} FcObjectType; } FcObjectType;

View File

@ -192,6 +192,8 @@ FcFini (void)
FcConfigFini (); FcConfigFini ();
FcCacheFini (); FcCacheFini ();
FcDefaultFini (); FcDefaultFini ();
FcObjectFini ();
FcConfigPathFini ();
} }
/* /*

View File

@ -880,6 +880,9 @@ FcPrivate FcConfig *
FcInitLoadOwnConfigAndFonts (FcConfig *config); FcInitLoadOwnConfigAndFonts (FcConfig *config);
/* fcxml.c */ /* fcxml.c */
FcPrivate void
FcConfigPathFini (void);
FcPrivate void FcPrivate void
FcTestDestroy (FcTest *test); FcTestDestroy (FcTest *test);
@ -1192,6 +1195,9 @@ FcStrSerialize (FcSerialize *serialize, const FcChar8 *str);
/* fcobjs.c */ /* fcobjs.c */
FcPrivate void
FcObjectFini (void);
FcPrivate FcObject FcPrivate FcObject
FcObjectLookupIdByName (const char *str); FcObjectLookupIdByName (const char *str);

View File

@ -44,6 +44,26 @@ struct FcObjectOtherTypeInfo {
FcObject id; FcObject id;
} *other_types; } *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 * static FcObjectType *
_FcObjectLookupOtherTypeByName (const char *str, FcObject *id) _FcObjectLookupOtherTypeByName (const char *str, FcObject *id)
{ {
@ -62,13 +82,16 @@ retry:
if (!ot) if (!ot)
return NULL; return NULL;
ot->object.object = (const char *) FcStrdup (str); ot->object.object = (char *) FcStrdup (str);
ot->object.type = FcTypeUnknown; ot->object.type = FcTypeUnknown;
ot->id = fc_atomic_int_add (next_id, +1); ot->id = fc_atomic_int_add (next_id, +1);
ot->next = ots; ot->next = ots;
if (!fc_atomic_ptr_cmpexch (&other_types, ots, ot)) { if (!fc_atomic_ptr_cmpexch (&other_types, ots, ot)) {
if (ot->object.object)
free (ot->object.object);
free (ot); free (ot);
fc_atomic_int_add (next_id, -1);
goto retry; goto retry;
} }
} }

View File

@ -57,6 +57,9 @@
extern FcChar8 fontconfig_instprefix[]; extern FcChar8 fontconfig_instprefix[];
#endif #endif
static FcChar8 *__fc_userdir = NULL;
static FcChar8 *__fc_userconf = NULL;
static void static void
FcExprDestroy (FcExpr *e); FcExprDestroy (FcExpr *e);
@ -2262,6 +2265,24 @@ FcParseCacheDir (FcConfigParse *parse)
FcStrFree (data); 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 static void
FcParseInclude (FcConfigParse *parse) FcParseInclude (FcConfigParse *parse)
{ {
@ -2272,8 +2293,7 @@ FcParseInclude (FcConfigParse *parse)
FcBool deprecated = FcFalse; FcBool deprecated = FcFalse;
#endif #endif
FcChar8 *prefix = NULL, *p; FcChar8 *prefix = NULL, *p;
static FcChar8 *userdir = NULL; FcChar8 userdir, userconf;
static FcChar8 *userconf = NULL;
s = FcStrBufDoneStatic (&parse->pstack->str); s = FcStrBufDoneStatic (&parse->pstack->str);
if (!s) if (!s)
@ -2303,6 +2323,7 @@ FcParseInclude (FcConfigParse *parse)
{ {
size_t plen = strlen ((const char *)prefix); size_t plen = strlen ((const char *)prefix);
size_t dlen = strlen ((const char *)s); size_t dlen = strlen ((const char *)s);
FcChar8 *u;
p = realloc (prefix, plen + 1 + dlen + 1); p = realloc (prefix, plen + 1 + dlen + 1);
if (!p) if (!p)
@ -2318,14 +2339,32 @@ FcParseInclude (FcConfigParse *parse)
if (FcFileIsDir (s)) if (FcFileIsDir (s))
{ {
userdir: userdir:
userdir = fc_atomic_ptr_get (&__fc_userdir);
if (!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)) else if (FcFileIsFile (s))
{ {
userconf: userconf:
userconf = fc_atomic_ptr_get (&__fc_userconf);
if (!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 else
{ {