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:
parent
e6967c513d
commit
f73ba331c1
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user