Commit e6967c51 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Validate 'CBLC' data before using it.

parent 1ee96850
...@@ -216,6 +216,9 @@ struct dwrite_fonttable ...@@ -216,6 +216,9 @@ struct dwrite_fonttable
BOOL exists; BOOL exists;
}; };
extern const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag,
struct dwrite_fonttable *table) DECLSPEC_HIDDEN;
extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,BOOL*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,UINT32*) DECLSPEC_HIDDEN; extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,BOOL*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,UINT32*) DECLSPEC_HIDDEN;
extern HRESULT opentype_get_font_table(struct file_stream_desc*,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN; extern HRESULT opentype_get_font_table(struct file_stream_desc*,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN;
extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *table, unsigned int max_count, extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *table, unsigned int max_count,
......
...@@ -338,7 +338,7 @@ static HRESULT set_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 ...@@ -338,7 +338,7 @@ static HRESULT set_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16
return S_OK; return S_OK;
} }
static const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag, struct dwrite_fonttable *table) const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag, struct dwrite_fonttable *table)
{ {
HRESULT hr; HRESULT hr;
......
...@@ -268,17 +268,19 @@ typedef struct { ...@@ -268,17 +268,19 @@ typedef struct {
WORD numGlyphs; WORD numGlyphs;
} maxp; } maxp;
typedef struct { struct cblc_header
WORD majorVersion; {
WORD minorVersion; WORD major_version;
DWORD numSizes; WORD minor_version;
} CBLCHeader; DWORD num_sizes;
};
typedef struct { typedef struct {
BYTE res[12]; BYTE res[12];
} sbitLineMetrics; } sbitLineMetrics;
typedef struct { struct cblc_bitmapsize_table
{
DWORD indexSubTableArrayOffset; DWORD indexSubTableArrayOffset;
DWORD indexTablesSize; DWORD indexTablesSize;
DWORD numberofIndexSubTables; DWORD numberofIndexSubTables;
...@@ -289,9 +291,9 @@ typedef struct { ...@@ -289,9 +291,9 @@ typedef struct {
WORD endGlyphIndex; WORD endGlyphIndex;
BYTE ppemX; BYTE ppemX;
BYTE ppemY; BYTE ppemY;
BYTE bitDepth; BYTE bit_depth;
BYTE flags; BYTE flags;
} CBLCBitmapSizeTable; };
struct gasp_range struct gasp_range
{ {
...@@ -2284,36 +2286,39 @@ static DWORD opentype_get_sbix_formats(IDWriteFontFace4 *fontface) ...@@ -2284,36 +2286,39 @@ static DWORD opentype_get_sbix_formats(IDWriteFontFace4 *fontface)
return ret; return ret;
} }
static UINT32 opentype_get_cblc_formats(IDWriteFontFace4 *fontface) static unsigned int opentype_get_cblc_formats(IDWriteFontFace4 *fontface)
{ {
CBLCBitmapSizeTable *sizes; const unsigned int format_mask = DWRITE_GLYPH_IMAGE_FORMATS_PNG |
UINT32 num_sizes, size, s; DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8;
BOOL exists = FALSE; const struct cblc_bitmapsize_table *sizes;
CBLCHeader *header; struct dwrite_fonttable cblc = { 0 };
UINT32 ret = 0; unsigned int num_sizes, i, ret = 0;
void *context; const struct cblc_header *header;
HRESULT hr;
if (FAILED(hr = IDWriteFontFace4_TryGetFontTable(fontface, MS_CBLC_TAG, (const void **)&header, &size, cblc.exists = TRUE;
&context, &exists))) if (!get_fontface_table(fontface, MS_CBLC_TAG, &cblc))
return 0; return 0;
if (!exists) num_sizes = table_read_be_dword(&cblc, FIELD_OFFSET(struct cblc_header, num_sizes));
return 0; sizes = table_read_ensure(&cblc, sizeof(*header), num_sizes * sizeof(*sizes));
num_sizes = GET_BE_DWORD(header->numSizes); if (sizes)
sizes = (CBLCBitmapSizeTable *)(header + 1); {
for (i = 0; i < num_sizes; ++i)
{
BYTE bpp = sizes[i].bit_depth;
for (s = 0; s < num_sizes; s++) { if ((ret & format_mask) == format_mask)
BYTE bpp = sizes->bitDepth; break;
if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8) if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8)
ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG; ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
else if (bpp == 32) else if (bpp == 32)
ret |= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8; ret |= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8;
}
} }
IDWriteFontFace4_ReleaseFontTable(fontface, context); IDWriteFontFace4_ReleaseFontTable(fontface, cblc.context);
return ret; return ret;
} }
......
...@@ -8755,7 +8755,7 @@ static DWORD get_cblc_formats(IDWriteFontFace4 *fontface) ...@@ -8755,7 +8755,7 @@ static DWORD get_cblc_formats(IDWriteFontFace4 *fontface)
sizes = (CBLCBitmapSizeTable *)(header + 1); sizes = (CBLCBitmapSizeTable *)(header + 1);
for (s = 0; s < num_sizes; s++) { for (s = 0; s < num_sizes; s++) {
BYTE bpp = sizes->bitDepth; BYTE bpp = sizes[s].bitDepth;
if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8) if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8)
ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG; ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
......
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