From e6967c513d0dab398bdd0c216bb5366ca465047c Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 29 Jan 2019 10:06:43 +0300 Subject: [PATCH] dwrite: Validate 'CBLC' data before using it. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/dwrite_private.h | 3 ++ dlls/dwrite/font.c | 2 +- dlls/dwrite/opentype.c | 63 +++++++++++++++++++----------------- dlls/dwrite/tests/font.c | 2 +- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 3251e66dec4..2d20b41ea67 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -216,6 +216,9 @@ struct dwrite_fonttable 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_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, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index bb04df6bd28..372578ec485 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -338,7 +338,7 @@ static HRESULT set_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 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; diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 82491dcc02e..261d00c8a85 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -268,17 +268,19 @@ typedef struct { WORD numGlyphs; } maxp; -typedef struct { - WORD majorVersion; - WORD minorVersion; - DWORD numSizes; -} CBLCHeader; +struct cblc_header +{ + WORD major_version; + WORD minor_version; + DWORD num_sizes; +}; typedef struct { BYTE res[12]; } sbitLineMetrics; -typedef struct { +struct cblc_bitmapsize_table +{ DWORD indexSubTableArrayOffset; DWORD indexTablesSize; DWORD numberofIndexSubTables; @@ -289,9 +291,9 @@ typedef struct { WORD endGlyphIndex; BYTE ppemX; BYTE ppemY; - BYTE bitDepth; + BYTE bit_depth; BYTE flags; -} CBLCBitmapSizeTable; +}; struct gasp_range { @@ -2284,36 +2286,39 @@ static DWORD opentype_get_sbix_formats(IDWriteFontFace4 *fontface) return ret; } -static UINT32 opentype_get_cblc_formats(IDWriteFontFace4 *fontface) +static unsigned int opentype_get_cblc_formats(IDWriteFontFace4 *fontface) { - CBLCBitmapSizeTable *sizes; - UINT32 num_sizes, size, s; - BOOL exists = FALSE; - CBLCHeader *header; - UINT32 ret = 0; - void *context; - HRESULT hr; + const unsigned int format_mask = DWRITE_GLYPH_IMAGE_FORMATS_PNG | + DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8; + const struct cblc_bitmapsize_table *sizes; + struct dwrite_fonttable cblc = { 0 }; + unsigned int num_sizes, i, ret = 0; + const struct cblc_header *header; - if (FAILED(hr = IDWriteFontFace4_TryGetFontTable(fontface, MS_CBLC_TAG, (const void **)&header, &size, - &context, &exists))) + cblc.exists = TRUE; + if (!get_fontface_table(fontface, MS_CBLC_TAG, &cblc)) return 0; - if (!exists) - return 0; + num_sizes = table_read_be_dword(&cblc, FIELD_OFFSET(struct cblc_header, num_sizes)); + sizes = table_read_ensure(&cblc, sizeof(*header), num_sizes * sizeof(*sizes)); - num_sizes = GET_BE_DWORD(header->numSizes); - sizes = (CBLCBitmapSizeTable *)(header + 1); + if (sizes) + { + for (i = 0; i < num_sizes; ++i) + { + BYTE bpp = sizes[i].bit_depth; - for (s = 0; s < num_sizes; s++) { - BYTE bpp = sizes->bitDepth; + if ((ret & format_mask) == format_mask) + break; - if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8) - ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG; - else if (bpp == 32) - ret |= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8; + if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8) + ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG; + else if (bpp == 32) + ret |= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8; + } } - IDWriteFontFace4_ReleaseFontTable(fontface, context); + IDWriteFontFace4_ReleaseFontTable(fontface, cblc.context); return ret; } diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 3e736c82b78..309c0a2b086 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -8755,7 +8755,7 @@ static DWORD get_cblc_formats(IDWriteFontFace4 *fontface) sizes = (CBLCBitmapSizeTable *)(header + 1); 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) ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;