From 2ca9aa16b2e68cc3e4bfa4fe45c6676a6aed0b89 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 29 Jan 2019 10:06:45 +0300 Subject: [PATCH] dwrite: Validate 'VDMX' data before using it. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/dwrite_private.h | 3 +- dlls/dwrite/font.c | 5 ++- dlls/dwrite/opentype.c | 82 +++++++++++++++++++++--------------- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 2d20b41ea67..3595503f1e5 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -229,7 +229,8 @@ extern HRESULT opentype_get_font_info_strings(const void*,DWRITE_INFORMATIONAL_S extern HRESULT opentype_get_font_familyname(struct file_stream_desc*,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; extern HRESULT opentype_get_font_facename(struct file_stream_desc*,WCHAR*,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; extern HRESULT opentype_get_typographic_features(IDWriteFontFace*,UINT32,UINT32,UINT32,UINT32*,DWRITE_FONT_FEATURE_TAG*) DECLSPEC_HIDDEN; -extern BOOL opentype_get_vdmx_size(const void*,INT,UINT16*,UINT16*) DECLSPEC_HIDDEN; +extern BOOL opentype_get_vdmx_size(const struct dwrite_fonttable *table, INT ppem, UINT16 *ascent, + UINT16 *descent) DECLSPEC_HIDDEN; extern unsigned int opentype_get_cpal_palettecount(const struct dwrite_fonttable *table) DECLSPEC_HIDDEN; extern unsigned int opentype_get_cpal_paletteentrycount(const struct dwrite_fonttable *table) DECLSPEC_HIDDEN; extern HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *table, unsigned int palette, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 372578ec485..d1e4fb97258 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -374,9 +374,10 @@ static FLOAT get_font_prop_vec_dotproduct(const struct dwrite_font_propvec *left return left->stretch * right->stretch + left->style * right->style + left->weight * right->weight; } -static const void* get_fontface_vdmx(struct dwrite_fontface *fontface) +static const struct dwrite_fonttable *get_fontface_vdmx(struct dwrite_fontface *fontface) { - return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_VDMX_TAG, &fontface->vdmx); + get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_VDMX_TAG, &fontface->vdmx); + return &fontface->vdmx; } static const struct dwrite_fonttable *get_fontface_gasp(struct dwrite_fontface *fontface) diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 35cf838cf03..f92febd2e03 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -343,14 +343,14 @@ typedef struct { TT_NameRecord nameRecord[1]; } TT_NAME_V0; -struct VDMX_Header +struct vdmx_header { WORD version; - WORD numRecs; - WORD numRatios; + WORD num_recs; + WORD num_ratios; }; -struct VDMX_Ratio +struct vdmx_ratio { BYTE bCharSet; BYTE xRatio; @@ -358,20 +358,21 @@ struct VDMX_Ratio BYTE yEndRatio; }; -struct VDMX_group -{ - WORD recs; - BYTE startsz; - BYTE endsz; -}; - -struct VDMX_vTable +struct vdmx_vtable { WORD yPelHeight; SHORT yMax; SHORT yMin; }; +struct vdmx_group +{ + WORD recs; + BYTE startsz; + BYTE endsz; + struct vdmx_vtable entries[1]; +}; + typedef struct { CHAR FeatureTag[4]; WORD Feature; @@ -1911,13 +1912,14 @@ HRESULT opentype_get_typographic_features(IDWriteFontFace *fontface, UINT32 scri return *count > max_tagcount ? E_NOT_SUFFICIENT_BUFFER : S_OK; } -static const struct VDMX_group *find_vdmx_group(const struct VDMX_Header *hdr) +static unsigned int find_vdmx_group(const struct vdmx_header *hdr) { - WORD num_ratios, i, group_offset = 0; - struct VDMX_Ratio *ratios = (struct VDMX_Ratio*)(hdr + 1); + WORD num_ratios, i; + const struct vdmx_ratio *ratios = (struct vdmx_ratio *)(hdr + 1); BYTE dev_x_ratio = 1, dev_y_ratio = 1; + unsigned int group_offset = 0; - num_ratios = GET_BE_WORD(hdr->numRatios); + num_ratios = GET_BE_WORD(hdr->num_ratios); for (i = 0; i < num_ratios; i++) { @@ -1932,42 +1934,56 @@ static const struct VDMX_group *find_vdmx_group(const struct VDMX_Header *hdr) break; } } - if (group_offset) - return (const struct VDMX_group *)((BYTE *)hdr + group_offset); - return NULL; + + return group_offset; } -BOOL opentype_get_vdmx_size(const void *data, INT emsize, UINT16 *ascent, UINT16 *descent) +BOOL opentype_get_vdmx_size(const struct dwrite_fonttable *vdmx, INT emsize, UINT16 *ascent, UINT16 *descent) { - const struct VDMX_Header *hdr = (const struct VDMX_Header*)data; - const struct VDMX_group *group; - const struct VDMX_vTable *tables; - WORD recs, i; + unsigned int num_ratios, num_recs, group_offset, i; + const struct vdmx_header *header; + const struct vdmx_group *group; - if (!data) + if (!vdmx->exists) return FALSE; - group = find_vdmx_group(hdr); + num_ratios = table_read_be_word(vdmx, FIELD_OFFSET(struct vdmx_header, num_ratios)); + num_recs = table_read_be_word(vdmx, FIELD_OFFSET(struct vdmx_header, num_recs)); + + header = table_read_ensure(vdmx, 0, sizeof(*header) + num_ratios * sizeof(struct vdmx_ratio) + + num_recs * sizeof(*group)); + + if (!header) + return FALSE; + + group_offset = find_vdmx_group(header); + if (!group_offset) + return FALSE; + + num_recs = table_read_be_word(vdmx, group_offset); + group = table_read_ensure(vdmx, group_offset, FIELD_OFFSET(struct vdmx_group, entries[num_recs])); + if (!group) return FALSE; - recs = GET_BE_WORD(group->recs); - if (emsize < group->startsz || emsize >= group->endsz) return FALSE; + if (emsize < group->startsz || emsize >= group->endsz) + return FALSE; - tables = (const struct VDMX_vTable *)(group + 1); - for (i = 0; i < recs; i++) { - WORD ppem = GET_BE_WORD(tables[i].yPelHeight); + for (i = 0; i < num_recs; ++i) + { + WORD ppem = GET_BE_WORD(group->entries[i].yPelHeight); if (ppem > emsize) { FIXME("interpolate %d\n", emsize); return FALSE; } if (ppem == emsize) { - *ascent = (SHORT)GET_BE_WORD(tables[i].yMax); - *descent = -(SHORT)GET_BE_WORD(tables[i].yMin); + *ascent = (SHORT)GET_BE_WORD(group->entries[i].yMax); + *descent = -(SHORT)GET_BE_WORD(group->entries[i].yMin); return TRUE; } } + return FALSE; }