[PATCH 4/4] dwrite: Validate 'VDMX' data before using it.

Nikolay Sivov nsivov at codeweavers.com
Tue Jan 29 01:06:45 CST 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 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 2d20b41ea6..3595503f1e 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 372578ec48..d1e4fb9725 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 35cf838cf0..f92febd2e0 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 (!vdmx->exists)
+        return FALSE;
+
+    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;
 
-    if (!data)
+    group_offset = find_vdmx_group(header);
+    if (!group_offset)
         return FALSE;
 
-    group = find_vdmx_group(hdr);
+    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;
 }
 
-- 
2.20.1




More information about the wine-devel mailing list