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 _FcObjectType {
const char *object;
char *object;
FcType type;
} FcObjectType;

View File

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

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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
{