Avoid null pointer dereference in FcNameParse if malloc fails
[platform/upstream/fontconfig.git] / src / fcname.c
index 0cdbd42..f302948 100644 (file)
 #include <string.h>
 #include <stdio.h>
 
-/*
- * Please do not change this list, it is used to initialize the object
- * list in this order to match the FC_foo_OBJECT constants. Those
- * constants are written into cache files.
- */
-
-static const FcObjectType _FcBaseObjectTypes[] = {
-    { FC_FAMILY,       FcTypeString, },    /* 1 */
-    { FC_FAMILYLANG,   FcTypeString, },
-    { FC_STYLE,                FcTypeString, },
-    { FC_STYLELANG,    FcTypeString, },
-    { FC_FULLNAME,     FcTypeString, },
-    { FC_FULLNAMELANG, FcTypeString, },
-    { FC_SLANT,                FcTypeInteger, },
-    { FC_WEIGHT,       FcTypeInteger, },
-    { FC_WIDTH,                FcTypeInteger, },
-    { FC_SIZE,         FcTypeDouble, },
-    { FC_ASPECT,       FcTypeDouble, },
-    { FC_PIXEL_SIZE,   FcTypeDouble, },
-    { FC_SPACING,      FcTypeInteger, },
-    { FC_FOUNDRY,      FcTypeString, },
-    { FC_ANTIALIAS,    FcTypeBool, },
-    { FC_HINT_STYLE,    FcTypeInteger, },
-    { FC_HINTING,      FcTypeBool, },
-    { FC_VERTICAL_LAYOUT,   FcTypeBool, },
-    { FC_AUTOHINT,     FcTypeBool, },
-    { FC_GLOBAL_ADVANCE,    FcTypeBool, },     /* deprecated */
-    { FC_FILE,         FcTypeString, },
-    { FC_INDEX,                FcTypeInteger, },
-    { FC_RASTERIZER,   FcTypeString, },
-    { FC_OUTLINE,      FcTypeBool, },
-    { FC_SCALABLE,     FcTypeBool, },
-    { FC_DPI,          FcTypeDouble },
-    { FC_RGBA,         FcTypeInteger, },
-    { FC_SCALE,                FcTypeDouble, },
-    { FC_MINSPACE,     FcTypeBool, },
-    { FC_CHAR_WIDTH,   FcTypeInteger },
-    { FC_CHAR_HEIGHT,  FcTypeInteger },
-    { FC_MATRIX,       FcTypeMatrix },
-    { FC_CHARSET,      FcTypeCharSet },
-    { FC_LANG,         FcTypeLangSet },
-    { FC_FONTVERSION,  FcTypeInteger },
-    { FC_CAPABILITY,   FcTypeString },
-    { FC_FONTFORMAT,   FcTypeString },
-    { FC_EMBOLDEN,     FcTypeBool },
-    { FC_EMBEDDED_BITMAP,   FcTypeBool },
-    { FC_DECORATIVE,   FcTypeBool },
-    { FC_LCD_FILTER,   FcTypeInteger }, /* 41 */
-    { FC_NAMELANG,     FcTypeString }, /* 42 */
-};
-
-#define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
-
-typedef struct _FcObjectTypeList    FcObjectTypeList;
-
-struct _FcObjectTypeList {
-    const FcObjectTypeList  *next;
-    const FcObjectType     *types;
-    int                            ntypes;
+static const FcObjectType FcObjects[] = {
+#define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME, Type },
+#include "fcobjs.h"
+#undef FC_OBJECT
 };
 
-static const FcObjectTypeList _FcBaseObjectTypesList = {
-    0,
-    _FcBaseObjectTypes,
-    NUM_OBJECT_TYPES,
-};
-
-static const FcObjectTypeList  *_FcObjectTypes = &_FcBaseObjectTypesList;
-
-#define OBJECT_HASH_SIZE    31
-
-typedef struct _FcObjectBucket {
-    struct _FcObjectBucket  *next;
-    FcChar32               hash;
-    FcObject               id;
-} FcObjectBucket;
-
-static FcObjectBucket  *FcObjectBuckets[OBJECT_HASH_SIZE];
-
-static FcObjectType    *FcObjects = (FcObjectType *) _FcBaseObjectTypes;
-static int             FcObjectsNumber = NUM_OBJECT_TYPES;
-static int             FcObjectsSize = 0;
-static FcBool          FcObjectsInited;
-
-static FcObjectType *
-FcObjectInsert (const char *name, FcType type)
-{
-    FcObjectType    *o;
-    if (FcObjectsNumber >= FcObjectsSize)
-    {
-       int             newsize = FcObjectsNumber * 2;
-       FcObjectType    *newobjects;
-       
-       if (FcObjectsSize)
-           newobjects = realloc (FcObjects, newsize * sizeof (FcObjectType));
-       else
-       {
-           newobjects = malloc (newsize * sizeof (FcObjectType));
-           if (newobjects)
-               memcpy (newobjects, FcObjects,
-                       FcObjectsNumber * sizeof (FcObjectType));
-       }
-       if (!newobjects)
-           return NULL;
-       FcObjects = newobjects;
-       FcObjectsSize = newsize;
-    }
-    o = &FcObjects[FcObjectsNumber];
-    o->object = name;
-    o->type = type;
-    ++FcObjectsNumber;
-    return o;
-}
-
-static FcObject
-FcObjectId (FcObjectType *o)
-{
-    return o - FcObjects + 1;
-}
-
-static FcObjectType *
-FcObjectFindByName (const char *object, FcBool insert)
-{
-    FcChar32       hash = FcStringHash ((const FcChar8 *) object);
-    FcObjectBucket  **p;
-    FcObjectBucket  *b;
-    FcObjectType    *o;
-
-    if (!FcObjectsInited)
-       FcObjectInit ();
-    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
-    {
-       o = FcObjects + b->id - 1;
-        if (b->hash == hash && !strcmp (object, (o->object)))
-            return o;
-    }
-    if (!insert)
-       return NULL;
-    /*
-     * Hook it into the hash chain
-     */
-    b = malloc (sizeof(FcObjectBucket));
-    if (!b)
-       return NULL;
-    object = (const char *) FcStrCopy ((FcChar8 *) object);
-    if (!object) {
-       free (b);
-       return NULL;
-    }
-    o = FcObjectInsert (object, -1);
-    b->next = NULL;
-    b->hash = hash;
-    b->id = FcObjectId (o);
-    *p = b;
-    return o;
-}
+#define NUM_OBJECT_TYPES ((int) (sizeof FcObjects / sizeof FcObjects[0]))
 
-static FcObjectType *
+static const FcObjectType *
 FcObjectFindById (FcObject object)
 {
-    if (1 <= object && object <= FcObjectsNumber)
-       return FcObjects + object - 1;
-    return NULL;
-}
-
-static FcBool
-FcObjectHashInsert (const FcObjectType *object, FcBool copy)
-{
-    FcChar32       hash = FcStringHash ((const FcChar8 *) object->object);
-    FcObjectBucket  **p;
-    FcObjectBucket  *b;
-    FcObjectType    *o;
-
-    if (!FcObjectsInited)
-       FcObjectInit ();
-    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
-    {
-       o = FcObjects + b->id - 1;
-        if (b->hash == hash && !strcmp (object->object, o->object))
-            return FcFalse;
-    }
-    /*
-     * Hook it into the hash chain
-     */
-    b = malloc (sizeof(FcObjectBucket));
-    if (!b)
-       return FcFalse;
-    if (copy)
-    {
-       o = FcObjectInsert (object->object, object->type);
-       if (!o)
-       {
-           free (b);
-           return FcFalse;
-       }
-    }
-    else
-       o = (FcObjectType *) object;
-    b->next = NULL;
-    b->hash = hash;
-    b->id = FcObjectId (o);
-    *p = b;
-    return FcTrue;
-}
-
-static void
-FcObjectHashRemove (const FcObjectType *object, FcBool cleanobj)
-{
-    FcChar32       hash = FcStringHash ((const FcChar8 *) object->object);
-    FcObjectBucket  **p;
-    FcObjectBucket  *b;
-    FcObjectType    *o;
-
-    if (!FcObjectsInited)
-       FcObjectInit ();
-    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
-    {
-       o = FcObjects + b->id - 1;
-        if (b->hash == hash && !strcmp (object->object, o->object))
-       {
-           *p = b->next;
-           free (b);
-           if (cleanobj)
-           {
-               /* Clean up object array */
-               o->object = NULL;
-               o->type = -1;
-               while (FcObjects[FcObjectsNumber-1].object == NULL)
-                   --FcObjectsNumber;
-           }
-            break;
-       }
-    }
+    if (1 <= object && object <= NUM_OBJECT_TYPES)
+       return &FcObjects[object - 1];
+    return FcObjectLookupOtherTypeById (object);
 }
 
 FcBool
 FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
 {
-    int        i;
-
-    for (i = 0; i < ntypes; i++)
-       if (!FcObjectHashInsert (&types[i], FcTrue))
-           return FcFalse;
-    return FcTrue;
+    /* Deprecated. */
+    return FcFalse;
 }
 
 FcBool
 FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
 {
-    int        i;
-
-    for (i = 0; i < ntypes; i++)
-       FcObjectHashRemove (&types[i], FcTrue);
-    return FcTrue;
+    /* Deprecated. */
+    return FcFalse;
 }
 
 const FcObjectType *
 FcNameGetObjectType (const char *object)
 {
-    return FcObjectFindByName (object, FcFalse);
+    int id = FcObjectLookupBuiltinIdByName (object);
+
+    if (!id)
+       return FcObjectLookupOtherTypeByName (object);
+
+    return &FcObjects[id - 1];
 }
 
 FcBool
 FcObjectValidType (FcObject object, FcType type)
 {
-    FcObjectType    *t = FcObjectFindById (object);
+    const FcObjectType    *t = FcObjectFindById (object);
 
     if (t) {
        switch ((int) t->type) {
+       case FcTypeUnknown:
+           return FcTrue;
        case FcTypeDouble:
        case FcTypeInteger:
            if (type == FcTypeDouble || type == FcTypeInteger)
@@ -307,7 +88,7 @@ FcObjectValidType (FcObject object, FcType type)
                return FcTrue;
            break;
        default:
-           if (t->type == (unsigned int) -1 || type == t->type)
+           if (type == t->type)
                return FcTrue;
            break;
        }
@@ -319,11 +100,7 @@ FcObjectValidType (FcObject object, FcType type)
 FcObject
 FcObjectFromName (const char * name)
 {
-    FcObjectType    *o = FcObjectFindByName (name, FcTrue);
-
-    if (o)
-       return FcObjectId (o);
-    return 0;
+    return FcObjectLookupIdByName (name);
 }
 
 FcObjectSet *
@@ -334,61 +111,21 @@ FcObjectGetSet (void)
 
 
     os = FcObjectSetCreate ();
-    for (i = 0; i < FcObjectsNumber; i++)
+    for (i = 0; i < NUM_OBJECT_TYPES; i++)
        FcObjectSetAdd (os, FcObjects[i].object);
 
     return os;
 }
 
-FcBool
-FcObjectInit (void)
-{
-    unsigned int       i;
-
-    if (FcObjectsInited)
-       return FcTrue;
-
-    FcObjectsInited = FcTrue;
-    for (i = 0; i < NUM_OBJECT_TYPES; i++)
-       if (!FcObjectHashInsert (&_FcBaseObjectTypes[i], FcFalse))
-           return FcFalse;
-    return FcTrue;
-}
-
-void
-FcObjectFini (void)
-{
-    int                    i;
-    FcObjectBucket  *b, *next;
-
-    for (i = 0; i < OBJECT_HASH_SIZE; i++)
-    {
-       for (b = FcObjectBuckets[i]; b; b = next)
-       {
-           next = b->next;
-           free (b);
-       }
-       FcObjectBuckets[i] = 0;
-    }
-    for (i = 0; i < FcObjectsNumber; i++)
-       if (FcObjects[i].type == (unsigned int) -1)
-           free ((void*) FcObjects[i].object);
-    if (FcObjects != _FcBaseObjectTypes)
-       free (FcObjects);
-    FcObjects = (FcObjectType *) _FcBaseObjectTypes;
-    FcObjectsNumber = NUM_OBJECT_TYPES;
-    FcObjectsSize = 0;
-    FcObjectsInited = FcFalse;
-}
-
 const char *
 FcObjectName (FcObject object)
 {
-    FcObjectType    *o = FcObjectFindById (object);
+    const FcObjectType   *o = FcObjectFindById (object);
 
     if (o)
        return o->object;
-    return NULL;
+
+    return FcObjectLookupOtherNameById (object);
 }
 
 static const FcConstant _FcBaseConstants[] = {
@@ -414,7 +151,7 @@ static const FcConstant _FcBaseConstants[] = {
     { (FcChar8 *) "ultracondensed", "width",   FC_WIDTH_ULTRACONDENSED },
     { (FcChar8 *) "extracondensed", "width",   FC_WIDTH_EXTRACONDENSED },
     { (FcChar8 *) "condensed",     "width",    FC_WIDTH_CONDENSED },
-    { (FcChar8 *) "semicondensed", "width",    FC_WIDTH_SEMICONDENSED },
+    { (FcChar8 *) "semicondensed",  "width",   FC_WIDTH_SEMICONDENSED },
     { (FcChar8 *) "normal",        "width",    FC_WIDTH_NORMAL },
     { (FcChar8 *) "semiexpanded",   "width",   FC_WIDTH_SEMIEXPANDED },
     { (FcChar8 *) "expanded",      "width",    FC_WIDTH_EXPANDED },
@@ -457,68 +194,29 @@ static const FcConstant _FcBaseConstants[] = {
 
 #define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
 
-typedef struct _FcConstantList FcConstantList;
-
-struct _FcConstantList {
-    const FcConstantList    *next;
-    const FcConstant       *consts;
-    int                            nconsts;
-};
-
-static const FcConstantList _FcBaseConstantList = {
-    0,
-    _FcBaseConstants,
-    NUM_FC_CONSTANTS
-};
-
-static const FcConstantList    *_FcConstants = &_FcBaseConstantList;
-
 FcBool
 FcNameRegisterConstants (const FcConstant *consts, int nconsts)
 {
-    FcConstantList     *l;
-
-    l = (FcConstantList *) malloc (sizeof (FcConstantList));
-    if (!l)
-       return FcFalse;
-    l->consts = consts;
-    l->nconsts = nconsts;
-    l->next = _FcConstants;
-    _FcConstants = l;
-    return FcTrue;
+    /* Deprecated. */
+    return FcFalse;
 }
 
 FcBool
 FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
 {
-    const FcConstantList       *l, **prev;
-
-    for (prev = &_FcConstants;
-        (l = *prev);
-        prev = (const FcConstantList **) &(l->next))
-    {
-       if (l->consts == consts && l->nconsts == nconsts)
-       {
-           *prev = l->next;
-           free ((void *) l);
-           return FcTrue;
-       }
-    }
+    /* Deprecated. */
     return FcFalse;
 }
 
 const FcConstant *
 FcNameGetConstant (const FcChar8 *string)
 {
-    const FcConstantList    *l;
-    int                            i;
+    unsigned int           i;
+
+    for (i = 0; i < NUM_FC_CONSTANTS; i++)
+       if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
+           return &_FcBaseConstants[i];
 
-    for (l = _FcConstants; l; l = l->next)
-    {
-       for (i = 0; i < l->nconsts; i++)
-           if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
-               return &l->consts[i];
-    }
     return 0;
 }
 
@@ -583,7 +281,7 @@ FcNameConvert (FcType type, FcChar8 *string)
            v.u.i = atoi ((char *) string);
        break;
     case FcTypeString:
-       v.u.s = FcSharedStr (string);
+       v.u.s = FcStrdup (string);
        if (!v.u.s)
            v.type = FcTypeVoid;
        break;
@@ -595,7 +293,7 @@ FcNameConvert (FcType type, FcChar8 *string)
        v.u.d = strtod ((char *) string, 0);
        break;
     case FcTypeMatrix:
-       m.xx = m.yy = 1.; m.xy = m.yx = 0.;
+       FcMatrixInit (&m);
        sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
        v.u.m = FcMatrixCopy (&m);
        break;
@@ -622,6 +320,12 @@ FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *l
 
     while ((c = *cur))
     {
+       if (!isspace (c))
+           break;
+       ++cur;
+    }
+    while ((c = *cur))
+    {
        if (c == '\\')
        {
            ++cur;
@@ -716,6 +420,8 @@ FcNameParse (const FcChar8 *name)
                if ((c = FcNameGetConstant (save)))
                {
                    t = FcNameGetObjectType ((char *) c->object);
+                   if (t == NULL)
+                       goto bail2;
                    switch ((int) t->type) {
                    case FcTypeInteger:
                    case FcTypeDouble:
@@ -772,6 +478,7 @@ FcNameUnparseValue (FcStrBuf        *buf,
     FcValue v = FcValueCanonicalize(v0);
 
     switch (v.type) {
+    case FcTypeUnknown:
     case FcTypeVoid:
        return FcTrue;
     case FcTypeInteger:
@@ -830,8 +537,6 @@ FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
     FcChar8                buf_static[8192];
     int                            i;
     FcPatternElt           *e;
-    const FcObjectTypeList  *l;
-    const FcObjectType     *o;
 
     FcStrBufInit (&buf, buf_static, sizeof (buf_static));
     e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
@@ -848,28 +553,27 @@ FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
        if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
            goto bail0;
     }
-    for (l = _FcObjectTypes; l; l = l->next)
+    for (i = 0; i < NUM_OBJECT_TYPES; i++)
     {
-       for (i = 0; i < l->ntypes; i++)
+       FcObject id = i + 1;
+       const FcObjectType          *o;
+       o = &FcObjects[i];
+       if (!strcmp (o->object, FC_FAMILY) ||
+           !strcmp (o->object, FC_SIZE))
+           continue;
+    
+       e = FcPatternObjectFindElt (pat, id);
+       if (e)
        {
-           o = &l->types[i];
-           if (!strcmp (o->object, FC_FAMILY) ||
-               !strcmp (o->object, FC_SIZE))
-               continue;
-       
-           e = FcPatternObjectFindElt (pat, FcObjectFromName (o->object));
-           if (e)
-           {
-               if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
-                   goto bail0;
-               if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
-                   goto bail0;
-               if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
-                   goto bail0;
-               if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
-                                            (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
-                   goto bail0;
-           }
+           if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
+               goto bail0;
+           if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
+               goto bail0;
+           if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
+               goto bail0;
+           if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
+                                        (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
+               goto bail0;
        }
     }
     return FcStrBufDone (&buf);