]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcpat.c
Fix additional memory leaks reported by Ronny V. Vindenes: don't invoke
[fontconfig.git] / src / fcpat.c
index ad6afc0065b0e6bb27061bc444ad58410f82be40..0a6241b564184f37f9688487804f256a8762a871 100644 (file)
 #include <assert.h>
 #include "fcint.h"
 
-static FcPattern ** fcpatterns = 0;
+static FcPattern ** _fcPatterns = 0;
 static int fcpattern_bank_count = 0, fcpattern_ptr, fcpattern_count;
-static FcPatternElt ** fcpatternelts = 0;
+FcPatternElt ** _fcPatternElts = 0;
 static int fcpatternelt_ptr, fcpatternelt_count;
-static FcValueList ** fcvaluelists = 0;
+FcValueList ** _fcValueLists = 0;
 static int fcvaluelist_bank_count = 0, fcvaluelist_ptr, fcvaluelist_count;
 
-static const char *
-FcPatternFindFullFname (const FcPattern *p);
 static FcPatternEltPtr
 FcPatternEltPtrCreateDynamic (FcPatternElt * e);
+static FcBool
+FcStrHashed (const FcChar8 *name);
+
+static const char *
+FcPatternFindFullFname (const FcPattern *p);
 
 /* If you are trying to duplicate an FcPattern which will be used for
  * rendering, be aware that (internally) you also have to use
@@ -68,7 +71,8 @@ FcValueDestroy (FcValue v)
 {
     switch (v.type) {
     case FcTypeString:
-       FcStrFree ((FcChar8 *) v.u.s);
+        if (!FcStrHashed (v.u.s))
+            FcStrFree ((FcChar8 *) v.u.s);
        break;
     case FcTypeMatrix:
        FcMatrixFree ((FcMatrix *) v.u.m);
@@ -149,7 +153,8 @@ FcValueListDestroy (FcValueListPtr l)
     {
        switch (FcValueListPtrU(l)->value.type) {
        case FcTypeString:
-           FcStrFree ((FcChar8 *)FcValueListPtrU(l)->value.u.s);
+            if (!FcStrHashed ((FcChar8 *)FcValueListPtrU(l)->value.u.s))
+                FcStrFree ((FcChar8 *)FcValueListPtrU(l)->value.u.s);
            break;
        case FcTypeMatrix:
            FcMatrixFree ((FcMatrix *)FcValueListPtrU(l)->value.u.m);
@@ -869,7 +874,14 @@ FcPatternAddWithBinding  (FcPattern            *p,
     new = FcValueListPtrCreateDynamic(newp);
     FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
     /* dup string */
-    value = FcValueSave (value);
+    if (value.type == FcTypeString)
+    {
+       value.u.s = FcStrStaticName (value.u.s);
+       if (!value.u.s)
+           value.type = FcTypeVoid;
+    }
+    else
+       value = FcValueSave (value);
     if (value.type == FcTypeVoid)
        goto bail1;
 
@@ -1024,6 +1036,13 @@ FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
 {
     FcValue    v;
 
+    if (!s)
+    {
+       v.type = FcTypeVoid;
+       v.u.s = 0;
+       return FcPatternAdd (p, object, v, FcTrue);
+    }
+
     v.type = FcTypeString;
     v.u.s = FcStrStaticName(s);
     return FcPatternAdd (p, object, v, FcTrue);
@@ -1364,6 +1383,19 @@ static struct objectBucket {
     FcChar32           hash;
 } *FcObjectBuckets[OBJECT_HASH_SIZE];
 
+static FcBool
+FcStrHashed (const FcChar8 *name)
+{
+    FcChar32           hash = FcStringHash (name);
+    struct objectBucket        **p;
+    struct objectBucket        *b;
+
+    for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+       if (b->hash == hash && !strcmp ((char *)name, (char *) (b + 1)))
+            return FcTrue;
+    return FcFalse;
+}
+
 const FcChar8 *
 FcStrStaticName (const FcChar8 *name)
 {
@@ -1418,15 +1450,6 @@ FcPatternFini (void)
     FcObjectStaticNameFini ();
 }
 
-FcPatternElt *
-FcPatternEltU (FcPatternEltPtr pei)
-{
-    if (pei.bank == FC_BANK_DYNAMIC)
-       return pei.u.dyn;
-
-    return &fcpatternelts[FcCacheBankToIndex(pei.bank)][pei.u.stat];
-}
-
 static FcPatternEltPtr
 FcPatternEltPtrCreateDynamic (FcPatternElt * e)
 {
@@ -1456,7 +1479,7 @@ FcStrDistributeBytes (FcCache * metadata, void * block_ptr);
 static const FcChar8 *
 FcStrSerialize (int bank, const FcChar8 * s);
 static void *
-FcStrUnserialize (FcCache metadata, void *block_ptr);
+FcStrUnserialize (FcCache metadata, void *block_ptr);
 
 static void
 FcValueListNewBank (void);
@@ -1469,7 +1492,7 @@ FcValueListDistributeBytes (FcCache * metadata, void *block_ptr);
 static FcValueListPtr
 FcValueListSerialize(int bank, FcValueList *pi);
 static void *
-FcValueListUnserialize (FcCache metadata, void *block_ptr);
+FcValueListUnserialize (FcCache metadata, void *block_ptr);
 
 
 void
@@ -1516,27 +1539,27 @@ FcPatternEnsureBank (int bi)
     FcPatternElt **ep;
     int i;
 
-    if (!fcpatterns || fcpattern_bank_count <= bi)
+    if (!_fcPatterns || fcpattern_bank_count <= bi)
     {
        int new_count = bi + 4;
-       pp = realloc (fcpatterns, sizeof (FcPattern *) * new_count);
+       pp = realloc (_fcPatterns, sizeof (FcPattern *) * new_count);
        if (!pp)
            return 0;
 
        FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern *) * new_count);
-       fcpatterns = pp;
+       _fcPatterns = pp;
 
-       ep = realloc (fcpatternelts, sizeof (FcPatternElt *) * new_count);
+       ep = realloc (_fcPatternElts, sizeof (FcPatternElt *) * new_count);
        if (!ep)
            return 0;
 
        FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt *) * new_count);
-       fcpatternelts = ep;
+       _fcPatternElts = ep;
 
        for (i = fcpattern_bank_count; i < new_count; i++)
        {
-           fcpatterns[i] = 0;
-           fcpatternelts[i] = 0;
+           _fcPatterns[i] = 0;
+           _fcPatternElts[i] = 0;
        }
 
        fcpattern_bank_count = new_count;
@@ -1556,14 +1579,14 @@ FcPatternDistributeBytes (FcCache * metadata, void * block_ptr)
 
     fcpattern_ptr = 0;
     block_ptr = ALIGN(block_ptr, FcPattern);
-    fcpatterns[bi] = (FcPattern *)block_ptr;
+    _fcPatterns[bi] = (FcPattern *)block_ptr;
     block_ptr = (void *)((char *)block_ptr + 
                         (sizeof (FcPattern) * fcpattern_count));
     
     FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt) * fcpatternelt_count);
     fcpatternelt_ptr = 0;
     block_ptr = ALIGN(block_ptr, FcPatternElt);
-    fcpatternelts[bi] = (FcPatternElt *)block_ptr;
+    _fcPatternElts[bi] = (FcPatternElt *)block_ptr;
     block_ptr = (void *)((char *)block_ptr + 
                         (sizeof (FcPatternElt) * fcpatternelt_count));
 
@@ -1584,10 +1607,10 @@ FcPatternSerialize (int bank, FcPattern *old)
     FcValueListPtr v, nv_head, nvp;
     int i, elts, bi = FcCacheBankToIndex(bank);
 
-    p = &fcpatterns[bi][fcpattern_ptr++];
+    p = &_fcPatterns[bi][fcpattern_ptr++];
     p->bank = bank;
     elts = fcpatternelt_ptr;
-    nep = &fcpatternelts[bi][elts];
+    nep = &_fcPatternElts[bi][elts];
     if (!nep)
        return FcFalse;
 
@@ -1628,24 +1651,24 @@ FcPatternSerialize (int bank, FcPattern *old)
 }
 
 void *
-FcPatternUnserialize (FcCache metadata, void *block_ptr)
+FcPatternUnserialize (FcCache metadata, void *block_ptr)
 {
-    int bi = FcCacheBankToIndex(metadata.bank);
+    int bi = FcCacheBankToIndex(metadata->bank);
     if (!FcPatternEnsureBank(bi))
        return FcFalse;
 
-    FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * metadata.pattern_count);
+    FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * metadata->pattern_count);
     block_ptr = ALIGN(block_ptr, FcPattern);
-    fcpatterns[bi] = (FcPattern *)block_ptr;
+    _fcPatterns[bi] = (FcPattern *)block_ptr;
     block_ptr = (void *)((char *)block_ptr + 
-                        (sizeof (FcPattern) * metadata.pattern_count));
+                        (sizeof (FcPattern) * metadata->pattern_count));
     
     FcMemAlloc (FC_MEM_PATELT, 
-               sizeof (FcPatternElt) * metadata.patternelt_count);
+               sizeof (FcPatternElt) * metadata->patternelt_count);
     block_ptr = ALIGN(block_ptr, FcPatternElt);
-    fcpatternelts[bi] = (FcPatternElt *)block_ptr;
+    _fcPatternElts[bi] = (FcPatternElt *)block_ptr;
     block_ptr = (void *)((char *)block_ptr + 
-                        (sizeof (FcPatternElt) * metadata.patternelt_count));
+                        (sizeof (FcPatternElt) * metadata->patternelt_count));
        
     block_ptr = FcStrUnserialize (metadata, block_ptr);
     block_ptr = FcValueListUnserialize (metadata, block_ptr);
@@ -1706,19 +1729,19 @@ FcValueListEnsureBank (int bi)
 {
     FcValueList **pvl;
 
-    if (!fcvaluelists || fcvaluelist_bank_count <= bi)
+    if (!_fcValueLists || fcvaluelist_bank_count <= bi)
     {
        int new_count = bi + 2, i;
 
-       pvl = realloc (fcvaluelists, sizeof (FcValueList *) * new_count);
+       pvl = realloc (_fcValueLists, sizeof (FcValueList *) * new_count);
        if (!pvl)
            return FcFalse;
 
        FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList *) * new_count);
 
-       fcvaluelists = pvl;
+       _fcValueLists = pvl;
        for (i = fcvaluelist_bank_count; i < new_count; i++)
-           fcvaluelists[i] = 0;
+           _fcValueLists[i] = 0;
 
        fcvaluelist_bank_count = new_count;
     }
@@ -1736,7 +1759,7 @@ FcValueListDistributeBytes (FcCache * metadata, void *block_ptr)
     FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList) * fcvaluelist_count);
     fcvaluelist_ptr = 0;
     block_ptr = ALIGN(block_ptr, FcValueList);
-    fcvaluelists[bi] = (FcValueList *)block_ptr;
+    _fcValueLists[bi] = (FcValueList *)block_ptr;
     block_ptr = (void *)((char *)block_ptr + 
                         (sizeof (FcValueList) * fcvaluelist_count));
     metadata->valuelist_count = fcvaluelist_count;
@@ -1761,11 +1784,11 @@ FcValueListSerialize(int bank, FcValueList *pi)
        return new;
     }
 
-    fcvaluelists[bi][fcvaluelist_ptr] = *pi;
+    _fcValueLists[bi][fcvaluelist_ptr] = *pi;
     new.bank = bank;
     new.u.stat = fcvaluelist_ptr++;
-    fcvaluelists[bi][new.u.stat].value = FcValueCanonicalize (&pi->value);
-    v = &fcvaluelists[bi][new.u.stat].value;
+    _fcValueLists[bi][new.u.stat].value = FcValueCanonicalize (&pi->value);
+    v = &_fcValueLists[bi][new.u.stat].value;
     switch (v->type)
     {
     case FcTypeString:
@@ -1807,19 +1830,19 @@ FcValueListSerialize(int bank, FcValueList *pi)
 }
 
 static void *
-FcValueListUnserialize (FcCache metadata, void *block_ptr)
+FcValueListUnserialize (FcCache metadata, void *block_ptr)
 {
-    int bi = FcCacheBankToIndex(metadata.bank);
+    int bi = FcCacheBankToIndex(metadata->bank);
 
     if (!FcValueListEnsureBank(bi))
        return 0;
 
     FcMemAlloc (FC_MEM_VALLIST, 
-               sizeof (FcValueList) * metadata.valuelist_count);
+               sizeof (FcValueList) * metadata->valuelist_count);
     block_ptr = ALIGN(block_ptr, FcValueList);
-    fcvaluelists[bi] = (FcValueList *)block_ptr;
+    _fcValueLists[bi] = (FcValueList *)block_ptr;
     block_ptr = (void *)((char *)block_ptr + 
-                        (sizeof (FcValueList) * metadata.valuelist_count));
+                        (sizeof (FcValueList) * metadata->valuelist_count));
 
     block_ptr = FcCharSetUnserialize(metadata, block_ptr);
     block_ptr = FcLangSetUnserialize(metadata, block_ptr);
@@ -1827,15 +1850,6 @@ FcValueListUnserialize (FcCache metadata, void *block_ptr)
     return block_ptr;
 }
 
-FcValueList * 
-FcValueListPtrU (FcValueListPtr pi)
-{
-    if (pi.bank == FC_BANK_DYNAMIC)
-        return pi.u.dyn;
-
-    return &fcvaluelists[FcCacheBankToIndex(pi.bank)][pi.u.stat];
-}
-
 FcValueListPtr
 FcValueListPtrCreateDynamic(FcValueList * p)
 {
@@ -1881,6 +1895,7 @@ FcStrNeededBytes (const FcChar8 * s)
     struct objectBucket **p;
     struct objectBucket *b;
     int                 size;
+    FcChar8 *const null = 0;
 
     for (p = &FcStrBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
         if (b->hash == hash && !strcmp ((char *)s, (char *) (b + 1)))
@@ -1898,7 +1913,8 @@ FcStrNeededBytes (const FcChar8 * s)
      * incorrect to replace the with a memset, because the C
      * specification doesn't guarantee that the null pointer is
      * the same as the zero bit pattern. */
-    *(char **)((char *) (b + 1) + strlen((char *)s) + 1) = 0;
+    /* Misaligned pointers are not guaranteed to work, either! */
+    memcpy (((char *) (b + 1) + strlen((char *)s) + 1), &null, sizeof (null));
     *p = b;
 
     fcstr_count += strlen((char *)s) + 1;
@@ -1961,13 +1977,15 @@ FcStrSerialize (int bank, const FcChar8 * s)
     for (p = &FcStrBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
         if (b->hash == hash && !strcmp ((char *)s, (char *) (b + 1)))
        {
-           FcChar8 * t = *(FcChar8 **)(((FcChar8 *)(b + 1)) + strlen ((char *)s) + 1);
+           FcChar8 * t;
+           memcpy (&t, ((FcChar8 *)(b + 1)) + strlen ((char *)s) + 1, sizeof (FcChar8 *));
            if (!t)
            {
                strcpy((char *)(static_strs[bi] + fcstr_ptr), (char *)s);
-               *(FcChar8 **)((FcChar8 *) (b + 1) + strlen((char *)s) + 1) = (static_strs[bi] + fcstr_ptr);
+               t = static_strs[bi] + fcstr_ptr;
+               memcpy ((FcChar8 *) (b + 1) + strlen((char *)s) + 1, &t, sizeof (FcChar8 *));
                fcstr_ptr += strlen((char *)s) + 1;
-               t = *(FcChar8 **)(((FcChar8 *)(b + 1)) + strlen ((char *)s) + 1);
+               memcpy (&t, ((FcChar8 *)(b + 1)) + strlen ((char *)s) + 1, sizeof (FcChar8 *));
            }
            return t;
        }
@@ -1975,17 +1993,17 @@ FcStrSerialize (int bank, const FcChar8 * s)
 }
 
 static void *
-FcStrUnserialize (FcCache metadata, void *block_ptr)
+FcStrUnserialize (FcCache metadata, void *block_ptr)
 {
-    int bi = FcCacheBankToIndex(metadata.bank);
+    int bi = FcCacheBankToIndex(metadata->bank);
     if (!FcStrEnsureBank(bi))
        return 0;
 
-    FcMemAlloc (FC_MEM_STRING, sizeof (char) * metadata.str_count);
+    FcMemAlloc (FC_MEM_STRING, sizeof (char) * metadata->str_count);
     block_ptr = ALIGN (block_ptr, FcChar8);
     static_strs[bi] = (FcChar8 *)block_ptr;
     block_ptr = (void *)((char *)block_ptr + 
-                        (sizeof (char) * metadata.str_count));
+                        (sizeof (char) * metadata->str_count));
 
     return block_ptr;
 }
@@ -1993,7 +2011,7 @@ FcStrUnserialize (FcCache metadata, void *block_ptr)
 /* we don't store these in the FcPattern itself because
  * we don't want to serialize the directory names */
 
-/* I suppose this should be cleaned, too... */
+/* I suppose this should be cleaned upon termination, too... */
 typedef struct _FcPatternDirMapping {
     const FcPattern    *p;
     const char *fname;
@@ -2013,7 +2031,7 @@ FcPatternAddFullFname (const FcPattern *p, const char *fname)
     /* N.B. FcPatternHash fails, since it's contents-based, not
      * address-based, and we're in the process of mutating the FcPattern. */
     for (pb = &FcPatternDirBuckets
-             [((int)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
+             [((unsigned long)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
          pb->m.p != p && pb->next; 
          pb = pb->next)
         ;
@@ -2040,7 +2058,7 @@ FcPatternFindFullFname (const FcPattern *p)
     struct patternDirBucket    *pb;
 
     for (pb = &FcPatternDirBuckets
-             [((int)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE]; 
+             [((unsigned long)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE]; 
          pb; pb = pb->next)
        if (pb->m.p == p)
            return pb->m.fname;