Protect cache against future expansions of FcLangSet (adding new
orth files). Previously, doing so could change the size of
that struct. Indeed, that happened between 2.6.0 and 2.7.3, causing
crashes. Unfortunately, sizeof(FcLangSet) was not checked in fcarch.c.
This changes FcLangSet code to be able to cope with struct size changes.
And change cache format, hence bumping from 2 to 3.
* it means multiple copies of the font information.
*/
* it means multiple copies of the font information.
*/
-#define FC_CACHE_VERSION "2"
+#define FC_CACHE_VERSION "3"
#define FcTrue 1
#define FcFalse 0
#define FcTrue 1
#define FcFalse 0
#define FC_CACHE_MAGIC_MMAP 0xFC02FC04
#define FC_CACHE_MAGIC_ALLOC 0xFC02FC05
#define FC_CACHE_MAGIC_MMAP 0xFC02FC04
#define FC_CACHE_MAGIC_ALLOC 0xFC02FC05
-#define FC_CACHE_CONTENT_VERSION 2
+#define FC_CACHE_CONTENT_VERSION 3 /* also check FC_CACHE_VERSION */
struct _FcAtomic {
FcChar8 *file; /* original file name */
struct _FcAtomic {
FcChar8 *file; /* original file name */
#include "../fc-lang/fclang.h"
struct _FcLangSet {
#include "../fc-lang/fclang.h"
struct _FcLangSet {
- FcChar32 map[NUM_LANG_SET_MAP];
+ int map_size;
+ FcChar32 map[NUM_LANG_SET_MAP];
-#define FcLangSetBitSet(ls, id) ((ls)->map[(fcLangCharSetIndices[id])>>5] |= ((FcChar32) 1 << ((fcLangCharSetIndices[id]) & 0x1f)))
-#define FcLangSetBitGet(ls, id) (((ls)->map[(fcLangCharSetIndices[id])>>5] >> ((fcLangCharSetIndices[id]) & 0x1f)) & 1)
+static void
+FcLangSetBitSet (FcLangSet *ls,
+ unsigned int id)
+{
+ int bucket;
+
+ id = fcLangCharSetIndices[id];
+ bucket = id >> 5;
+ if (bucket >= ls->map_size)
+ return; /* shouldn't happen really */
+
+ ls->map[bucket] |= ((FcChar32) 1 << (id & 0x1f));
+}
+
+static FcBool
+FcLangSetBitGet (const FcLangSet *ls,
+ unsigned int id)
+{
+ int bucket;
+
+ id = fcLangCharSetIndices[id];
+ bucket = id >> 5;
+ if (bucket >= ls->map_size)
+ return FcFalse;
+
+ return ((ls->map[bucket] >> (id & 0x1f)) & 1) ? FcTrue : FcFalse;
+}
FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset,
FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset,
case FcLangDifferentTerritory:
if (country == -1)
country = i;
case FcLangDifferentTerritory:
if (country == -1)
country = i;
+ case FcLangDifferentLang:
return 0;
FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
memset (ls->map, '\0', sizeof (ls->map));
return 0;
FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
memset (ls->map, '\0', sizeof (ls->map));
+ ls->map_size = NUM_LANG_SET_MAP;
ls->extra = 0;
return ls;
}
ls->extra = 0;
return ls;
}
new = FcLangSetCreate ();
if (!new)
goto bail0;
new = FcLangSetCreate ();
if (!new)
goto bail0;
- memcpy (new->map, ls->map, sizeof (new->map));
+ memset (new->map, '\0', sizeof (new->map));
+ memcpy (new->map, ls->map, FC_MIN (sizeof (new->map), ls->map_size * sizeof (ls->map[0])));
if (ls->extra)
{
FcStrList *list;
if (ls->extra)
{
FcStrList *list;
FcLangResult
FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
{
FcLangResult
FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
{
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (lsa->map_size, lsb->map_size);
+ count = FC_MIN (NUM_LANG_SET_MAP, count);
+ for (i = 0; i < count; i++)
if (lsa->map[i] & lsb->map[i])
return FcLangEqual;
best = FcLangDifferentLang;
for (j = 0; j < NUM_COUNTRY_SET; j++)
if (lsa->map[i] & lsb->map[i])
return FcLangEqual;
best = FcLangDifferentLang;
for (j = 0; j < NUM_COUNTRY_SET; j++)
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ for (i = 0; i < count; i++)
if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
(lsb->map[i] & fcLangCountrySets[j][i]))
{
if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
(lsb->map[i] & fcLangCountrySets[j][i]))
{
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ for (i = 0; i < ls->map_size; i++)
h ^= ls->map[i];
if (ls->extra)
h ^= ls->extra->num;
h ^= ls->map[i];
if (ls->extra)
h ^= ls->extra->num;
FcLangSet *
FcNameParseLangSet (const FcChar8 *string)
{
FcLangSet *
FcNameParseLangSet (const FcChar8 *string)
{
+ FcChar8 lang[32], c = 0;
FcBool
FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
{
FcBool
FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
{
FcChar32 bits;
FcBool first = FcTrue;
FcChar32 bits;
FcBool first = FcTrue;
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (ls->map_size, NUM_LANG_SET_MAP);
+ for (i = 0; i < count; i++)
{
if ((bits = ls->map[i]))
{
{
if ((bits = ls->map[i]))
{
FcBool
FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
{
FcBool
FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
{
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (lsa->map_size, lsb->map_size);
+ count = FC_MIN (NUM_LANG_SET_MAP, count);
+ for (i = 0; i < count; i++)
{
if (lsa->map[i] != lsb->map[i])
return FcFalse;
{
if (lsa->map[i] != lsb->map[i])
return FcFalse;
FcBool
FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
{
FcBool
FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
{
FcChar32 missing;
if (FcDebug() & FC_DBG_MATCHV)
FcChar32 missing;
if (FcDebug() & FC_DBG_MATCHV)
/*
* check bitmaps for missing language support
*/
/*
* check bitmaps for missing language support
*/
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (lsa->map_size, lsb->map_size);
+ count = FC_MIN (NUM_LANG_SET_MAP, count);
+ for (i = 0; i < count; i++)
{
missing = lsb->map[i] & ~lsa->map[i];
if (missing)
{
missing = lsb->map[i] & ~lsa->map[i];
if (missing)
if (!l_serialize)
return NULL;
*l_serialize = *l;
if (!l_serialize)
return NULL;
*l_serialize = *l;
+ l_serialize->extra = NULL; /* We don't serialize ls->extra */