Commit 1ee96850 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Validate 'COLR' data before using it.

parent ca29ac46
...@@ -245,8 +245,10 @@ struct dwrite_colorglyph { ...@@ -245,8 +245,10 @@ struct dwrite_colorglyph {
UINT16 palette_index; UINT16 palette_index;
}; };
extern HRESULT opentype_get_colr_glyph(const void*,UINT16,struct dwrite_colorglyph*) DECLSPEC_HIDDEN; extern HRESULT opentype_get_colr_glyph(const struct dwrite_fonttable *table, UINT16 glyph,
extern void opentype_colr_next_glyph(const void*,struct dwrite_colorglyph*) DECLSPEC_HIDDEN; struct dwrite_colorglyph *color_glyph) DECLSPEC_HIDDEN;
extern void opentype_colr_next_glyph(const struct dwrite_fonttable *table,
struct dwrite_colorglyph *color_glyph) DECLSPEC_HIDDEN;
enum gasp_flags { enum gasp_flags {
GASP_GRIDFIT = 0x0001, GASP_GRIDFIT = 0x0001,
......
...@@ -5649,7 +5649,7 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen ...@@ -5649,7 +5649,7 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen
/* offsets are relative to glyph origin, nothing to fix up */ /* offsets are relative to glyph origin, nothing to fix up */
if (glyphenum->color_offsets) if (glyphenum->color_offsets)
glyphenum->color_offsets[index] = glyphenum->offsets[g]; glyphenum->color_offsets[index] = glyphenum->offsets[g];
opentype_colr_next_glyph(glyphenum->colr.data, glyphenum->glyphs + g); opentype_colr_next_glyph(&glyphenum->colr, glyphenum->glyphs + g);
if (index) if (index)
glyphenum->color_advances[index-1] += advance_adj; glyphenum->color_advances[index-1] += advance_adj;
colorrun->glyphRun.glyphCount++; colorrun->glyphRun.glyphCount++;
...@@ -5755,7 +5755,7 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R ...@@ -5755,7 +5755,7 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R
has_colored_glyph = FALSE; has_colored_glyph = FALSE;
colorglyphenum->has_regular_glyphs = FALSE; colorglyphenum->has_regular_glyphs = FALSE;
for (i = 0; i < run->glyphCount; i++) { for (i = 0; i < run->glyphCount; i++) {
if (opentype_get_colr_glyph(colorglyphenum->colr.data, run->glyphIndices[i], colorglyphenum->glyphs + i) == S_OK) { if (opentype_get_colr_glyph(&colorglyphenum->colr, run->glyphIndices[i], colorglyphenum->glyphs + i) == S_OK) {
colorglyphenum->max_layer_num = max(colorglyphenum->max_layer_num, colorglyphenum->glyphs[i].num_layers); colorglyphenum->max_layer_num = max(colorglyphenum->max_layer_num, colorglyphenum->glyphs[i].num_layers);
has_colored_glyph = TRUE; has_colored_glyph = TRUE;
} }
......
...@@ -862,26 +862,26 @@ struct cpal_color_record ...@@ -862,26 +862,26 @@ struct cpal_color_record
}; };
/* COLR table */ /* COLR table */
struct COLR_Header struct colr_header
{ {
USHORT version; USHORT version;
USHORT numBaseGlyphRecords; USHORT num_baseglyph_records;
ULONG offsetBaseGlyphRecord; ULONG offset_baseglyph_records;
ULONG offsetLayerRecord; ULONG offset_layer_records;
USHORT numLayerRecords; USHORT num_layer_records;
}; };
struct COLR_BaseGlyphRecord struct colr_baseglyph_record
{ {
USHORT GID; USHORT glyph;
USHORT firstLayerIndex; USHORT first_layer_index;
USHORT numLayers; USHORT num_layers;
}; };
struct COLR_LayerRecord struct colr_layer_record
{ {
USHORT GID; USHORT glyph;
USHORT paletteIndex; USHORT palette_index;
}; };
static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size) static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size)
...@@ -2050,8 +2050,8 @@ HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *cpal, unsigned ...@@ -2050,8 +2050,8 @@ HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *cpal, unsigned
static int colr_compare_gid(const void *g, const void *r) static int colr_compare_gid(const void *g, const void *r)
{ {
const struct COLR_BaseGlyphRecord *record = r; const struct colr_baseglyph_record *record = r;
UINT16 glyph = *(UINT16*)g, GID = GET_BE_WORD(record->GID); UINT16 glyph = *(UINT16*)g, GID = GET_BE_WORD(record->glyph);
int ret = 0; int ret = 0;
if (glyph > GID) if (glyph > GID)
...@@ -2062,51 +2062,68 @@ static int colr_compare_gid(const void *g, const void *r) ...@@ -2062,51 +2062,68 @@ static int colr_compare_gid(const void *g, const void *r)
return ret; return ret;
} }
HRESULT opentype_get_colr_glyph(const void *colr, UINT16 glyph, struct dwrite_colorglyph *ret) HRESULT opentype_get_colr_glyph(const struct dwrite_fonttable *colr, UINT16 glyph, struct dwrite_colorglyph *ret)
{ {
const struct COLR_BaseGlyphRecord *record; unsigned int num_baseglyph_records, offset_baseglyph_records;
const struct COLR_Header *header = colr; const struct colr_baseglyph_record *record;
const struct COLR_LayerRecord *layer; const struct colr_layer_record *layer;
DWORD layerrecordoffset = GET_BE_DWORD(header->offsetLayerRecord); const struct colr_header *header;
DWORD baserecordoffset = GET_BE_DWORD(header->offsetBaseGlyphRecord);
WORD numbaserecords = GET_BE_WORD(header->numBaseGlyphRecords); memset(ret, 0, sizeof(*ret));
ret->glyph = glyph;
record = bsearch(&glyph, (BYTE*)colr + baserecordoffset, numbaserecords, sizeof(struct COLR_BaseGlyphRecord), ret->palette_index = 0xffff;
colr_compare_gid);
if (!record) { header = table_read_ensure(colr, 0, sizeof(*header));
ret->layer = 0; if (!header)
ret->first_layer = 0; return S_FALSE;
ret->num_layers = 0;
ret->glyph = glyph; num_baseglyph_records = GET_BE_WORD(header->num_baseglyph_records);
ret->palette_index = 0xffff; offset_baseglyph_records = GET_BE_DWORD(header->offset_baseglyph_records);
if (!table_read_ensure(colr, offset_baseglyph_records, num_baseglyph_records * sizeof(*record)))
{
return S_FALSE; return S_FALSE;
} }
ret->layer = 0; record = bsearch(&glyph, colr->data + offset_baseglyph_records, num_baseglyph_records,
ret->first_layer = GET_BE_WORD(record->firstLayerIndex); sizeof(*record), colr_compare_gid);
ret->num_layers = GET_BE_WORD(record->numLayers); if (!record)
return S_FALSE;
ret->first_layer = GET_BE_WORD(record->first_layer_index);
ret->num_layers = GET_BE_WORD(record->num_layers);
layer = (struct COLR_LayerRecord*)((BYTE*)colr + layerrecordoffset) + ret->first_layer + ret->layer; if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records),
ret->glyph = GET_BE_WORD(layer->GID); (ret->first_layer + ret->layer) * sizeof(*layer))))
ret->palette_index = GET_BE_WORD(layer->paletteIndex); {
layer += ret->first_layer + ret->layer;
ret->glyph = GET_BE_WORD(layer->glyph);
ret->palette_index = GET_BE_WORD(layer->palette_index);
}
return S_OK; return S_OK;
} }
void opentype_colr_next_glyph(const void *colr, struct dwrite_colorglyph *glyph) void opentype_colr_next_glyph(const struct dwrite_fonttable *colr, struct dwrite_colorglyph *glyph)
{ {
const struct COLR_Header *header = colr; const struct colr_layer_record *layer;
const struct COLR_LayerRecord *layer; const struct colr_header *header;
DWORD layerrecordoffset = GET_BE_DWORD(header->offsetLayerRecord);
/* iterated all the way through */ /* iterated all the way through */
if (glyph->layer == glyph->num_layers) if (glyph->layer == glyph->num_layers)
return; return;
if (!(header = table_read_ensure(colr, 0, sizeof(*header))))
return;
glyph->layer++; glyph->layer++;
layer = (struct COLR_LayerRecord*)((BYTE*)colr + layerrecordoffset) + glyph->first_layer + glyph->layer;
glyph->glyph = GET_BE_WORD(layer->GID); if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records),
glyph->palette_index = GET_BE_WORD(layer->paletteIndex); (glyph->first_layer + glyph->layer) * sizeof(*layer))))
{
layer += glyph->first_layer + glyph->layer;
glyph->glyph = GET_BE_WORD(layer->glyph);
glyph->palette_index = GET_BE_WORD(layer->palette_index);
}
} }
BOOL opentype_has_vertical_variants(IDWriteFontFace4 *fontface) BOOL opentype_has_vertical_variants(IDWriteFontFace4 *fontface)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment