dwrite: Validate 'sbix' data before using it.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2019-01-29 10:06:44 +03:00 committed by Alexandre Julliard
parent e6967c513d
commit f73ba331c1

View File

@ -243,30 +243,34 @@ typedef struct {
USHORT numberOfHMetrics; USHORT numberOfHMetrics;
} TT_HHEA; } TT_HHEA;
typedef struct { struct sbix_header
{
WORD version; WORD version;
WORD flags; WORD flags;
DWORD numStrikes; DWORD num_strikes;
DWORD strikeOffset[1]; DWORD strike_offset[1];
} sbix_header; };
typedef struct { struct sbix_strike
{
WORD ppem; WORD ppem;
WORD ppi; WORD ppi;
DWORD glyphDataOffsets[1]; DWORD glyphdata_offsets[1];
} sbix_strike; };
typedef struct { struct sbix_glyph_data
{
WORD originOffsetX; WORD originOffsetX;
WORD originOffsetY; WORD originOffsetY;
DWORD graphicType; DWORD graphic_type;
BYTE data[1]; BYTE data[1];
} sbix_glyph_data; };
typedef struct { struct maxp
{
DWORD version; DWORD version;
WORD numGlyphs; WORD num_glyphs;
} maxp; };
struct cblc_header struct cblc_header
{ {
@ -2221,49 +2225,56 @@ static BOOL opentype_has_font_table(IDWriteFontFace4 *fontface, UINT32 tag)
return exists; return exists;
} }
static DWORD opentype_get_sbix_formats(IDWriteFontFace4 *fontface) static unsigned int opentype_get_sbix_formats(IDWriteFontFace4 *fontface)
{ {
UINT32 size, s, num_strikes; unsigned int num_strikes, num_glyphs, i, j, ret = 0;
const sbix_header *header; const struct sbix_header *sbix_header;
UINT16 g, num_glyphs; struct dwrite_fonttable table;
BOOL exists = FALSE;
const maxp *maxp;
const void *data;
DWORD ret = 0;
void *context;
HRESULT hr;
hr = IDWriteFontFace4_TryGetFontTable(fontface, MS_MAXP_TAG, &data, &size, &context, &exists); memset(&table, 0, sizeof(table));
if (FAILED(hr) || !exists) table.exists = TRUE;
if (!get_fontface_table(fontface, MS_MAXP_TAG, &table))
return 0; return 0;
maxp = data; num_glyphs = table_read_be_word(&table, FIELD_OFFSET(struct maxp, num_glyphs));
num_glyphs = GET_BE_WORD(maxp->numGlyphs);
IDWriteFontFace4_ReleaseFontTable(fontface, context); IDWriteFontFace4_ReleaseFontTable(fontface, table.context);
if (FAILED(IDWriteFontFace4_TryGetFontTable(fontface, MS_SBIX_TAG, &data, &size, &context, &exists))) { memset(&table, 0, sizeof(table));
WARN("Failed to get 'sbix' table, %#x\n", hr); table.exists = TRUE;
if (!get_fontface_table(fontface, MS_SBIX_TAG, &table))
return 0; return 0;
}
header = data; num_strikes = table_read_be_dword(&table, FIELD_OFFSET(struct sbix_header, num_strikes));
num_strikes = GET_BE_DWORD(header->numStrikes); sbix_header = table_read_ensure(&table, 0, FIELD_OFFSET(struct sbix_header, strike_offset[num_strikes]));
for (s = 0; s < num_strikes; s++) { if (sbix_header)
sbix_strike *strike = (sbix_strike *)((BYTE *)header + GET_BE_DWORD(header->strikeOffset[s])); {
for (i = 0; i < num_strikes; ++i)
{
unsigned int strike_offset = GET_BE_DWORD(sbix_header->strike_offset[i]);
const struct sbix_strike *strike = table_read_ensure(&table, strike_offset,
FIELD_OFFSET(struct sbix_strike, glyphdata_offsets[num_glyphs + 1]));
for (g = 0; g < num_glyphs; g++) { if (!strike)
DWORD offset = GET_BE_DWORD(strike->glyphDataOffsets[g]);
DWORD offset_next = GET_BE_DWORD(strike->glyphDataOffsets[g + 1]);
sbix_glyph_data *glyph_data;
DWORD format;
if (offset == offset_next)
continue; continue;
glyph_data = (sbix_glyph_data *)((BYTE *)strike + offset); for (j = 0; j < num_glyphs; j++)
switch (format = glyph_data->graphicType) {
unsigned int offset = GET_BE_DWORD(strike->glyphdata_offsets[j]);
unsigned int next_offset = GET_BE_DWORD(strike->glyphdata_offsets[j + 1]);
const struct sbix_glyph_data *glyph_data;
if (offset == next_offset)
continue;
glyph_data = table_read_ensure(&table, strike_offset + offset, sizeof(*glyph_data));
if (!glyph_data)
continue;
switch (glyph_data->graphic_type)
{ {
case MS_PNG__TAG: case MS_PNG__TAG:
ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG; ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
@ -2275,13 +2286,13 @@ static DWORD opentype_get_sbix_formats(IDWriteFontFace4 *fontface)
ret |= DWRITE_GLYPH_IMAGE_FORMATS_TIFF; ret |= DWRITE_GLYPH_IMAGE_FORMATS_TIFF;
break; break;
default: default:
format = GET_BE_DWORD(format); FIXME("unexpected bitmap format %s\n", debugstr_tag(GET_BE_DWORD(glyph_data->graphic_type)));
FIXME("unexpected bitmap format %s\n", debugstr_an((char *)&format, 4)); }
} }
} }
} }
IDWriteFontFace4_ReleaseFontTable(fontface, context); IDWriteFontFace4_ReleaseFontTable(fontface, table.context);
return ret; return ret;
} }