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

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


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h |   6 +-
 dlls/dwrite/font.c           |   4 +-
 dlls/dwrite/opentype.c       | 105 ++++++++++++++++++++---------------
 3 files changed, 67 insertions(+), 48 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 6eac1f4f33..3251e66dec 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -245,8 +245,10 @@ struct dwrite_colorglyph {
     UINT16 palette_index;
 };
 
-extern HRESULT opentype_get_colr_glyph(const void*,UINT16,struct dwrite_colorglyph*) DECLSPEC_HIDDEN;
-extern void opentype_colr_next_glyph(const void*,struct dwrite_colorglyph*) DECLSPEC_HIDDEN;
+extern HRESULT opentype_get_colr_glyph(const struct dwrite_fonttable *table, UINT16 glyph,
+        struct dwrite_colorglyph *color_glyph) DECLSPEC_HIDDEN;
+extern void opentype_colr_next_glyph(const struct dwrite_fonttable *table,
+        struct dwrite_colorglyph *color_glyph) DECLSPEC_HIDDEN;
 
 enum gasp_flags {
     GASP_GRIDFIT             = 0x0001,
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 2c51674b0a..bb04df6bd2 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -5649,7 +5649,7 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen
             /* offsets are relative to glyph origin, nothing to fix up */
             if (glyphenum->color_offsets)
                 glyphenum->color_offsets[index] = glyphenum->offsets[g];
-            opentype_colr_next_glyph(glyphenum->colr.data, glyphenum->glyphs + g);
+            opentype_colr_next_glyph(&glyphenum->colr, glyphenum->glyphs + g);
             if (index)
                 glyphenum->color_advances[index-1] += advance_adj;
             colorrun->glyphRun.glyphCount++;
@@ -5755,7 +5755,7 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R
     has_colored_glyph = FALSE;
     colorglyphenum->has_regular_glyphs = FALSE;
     for (i = 0; i < run->glyphCount; i++) {
-        if (opentype_get_colr_glyph(colorglyphenum->colr.data, run->glyphIndices[i], colorglyphenum->glyphs + i) == S_OK) {
+        if (opentype_get_colr_glyph(&colorglyphenum->colr, run->glyphIndices[i], colorglyphenum->glyphs + i) == S_OK) {
             colorglyphenum->max_layer_num = max(colorglyphenum->max_layer_num, colorglyphenum->glyphs[i].num_layers);
             has_colored_glyph = TRUE;
         }
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 647ac99597..82491dcc02 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -862,26 +862,26 @@ struct cpal_color_record
 };
 
 /* COLR table */
-struct COLR_Header
+struct colr_header
 {
     USHORT version;
-    USHORT numBaseGlyphRecords;
-    ULONG  offsetBaseGlyphRecord;
-    ULONG  offsetLayerRecord;
-    USHORT numLayerRecords;
+    USHORT num_baseglyph_records;
+    ULONG offset_baseglyph_records;
+    ULONG offset_layer_records;
+    USHORT num_layer_records;
 };
 
-struct COLR_BaseGlyphRecord
+struct colr_baseglyph_record
 {
-    USHORT GID;
-    USHORT firstLayerIndex;
-    USHORT numLayers;
+    USHORT glyph;
+    USHORT first_layer_index;
+    USHORT num_layers;
 };
 
-struct COLR_LayerRecord
+struct colr_layer_record
 {
-    USHORT GID;
-    USHORT paletteIndex;
+    USHORT glyph;
+    USHORT palette_index;
 };
 
 static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size)
@@ -2050,8 +2050,8 @@ HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *cpal, unsigned
 
 static int colr_compare_gid(const void *g, const void *r)
 {
-    const struct COLR_BaseGlyphRecord *record = r;
-    UINT16 glyph = *(UINT16*)g, GID = GET_BE_WORD(record->GID);
+    const struct colr_baseglyph_record *record = r;
+    UINT16 glyph = *(UINT16*)g, GID = GET_BE_WORD(record->glyph);
     int ret = 0;
 
     if (glyph > GID)
@@ -2062,51 +2062,68 @@ static int colr_compare_gid(const void *g, const void *r)
     return ret;
 }
 
-HRESULT opentype_get_colr_glyph(const void *colr, UINT16 glyph, struct dwrite_colorglyph *ret)
-{
-    const struct COLR_BaseGlyphRecord *record;
-    const struct COLR_Header *header = colr;
-    const struct COLR_LayerRecord *layer;
-    DWORD layerrecordoffset = GET_BE_DWORD(header->offsetLayerRecord);
-    DWORD baserecordoffset = GET_BE_DWORD(header->offsetBaseGlyphRecord);
-    WORD numbaserecords = GET_BE_WORD(header->numBaseGlyphRecords);
-
-    record = bsearch(&glyph, (BYTE*)colr + baserecordoffset, numbaserecords, sizeof(struct COLR_BaseGlyphRecord),
-        colr_compare_gid);
-    if (!record) {
-        ret->layer = 0;
-        ret->first_layer = 0;
-        ret->num_layers = 0;
-        ret->glyph = glyph;
-        ret->palette_index = 0xffff;
+HRESULT opentype_get_colr_glyph(const struct dwrite_fonttable *colr, UINT16 glyph, struct dwrite_colorglyph *ret)
+{
+    unsigned int num_baseglyph_records, offset_baseglyph_records;
+    const struct colr_baseglyph_record *record;
+    const struct colr_layer_record *layer;
+    const struct colr_header *header;
+
+    memset(ret, 0, sizeof(*ret));
+    ret->glyph = glyph;
+    ret->palette_index = 0xffff;
+
+    header = table_read_ensure(colr, 0, sizeof(*header));
+    if (!header)
+        return S_FALSE;
+
+    num_baseglyph_records = GET_BE_WORD(header->num_baseglyph_records);
+    offset_baseglyph_records = GET_BE_DWORD(header->offset_baseglyph_records);
+    if (!table_read_ensure(colr, offset_baseglyph_records, num_baseglyph_records * sizeof(*record)))
+    {
         return S_FALSE;
     }
 
-    ret->layer = 0;
-    ret->first_layer = GET_BE_WORD(record->firstLayerIndex);
-    ret->num_layers = GET_BE_WORD(record->numLayers);
+    record = bsearch(&glyph, colr->data + offset_baseglyph_records, num_baseglyph_records,
+            sizeof(*record), colr_compare_gid);
+    if (!record)
+        return S_FALSE;
+
+    ret->first_layer = GET_BE_WORD(record->first_layer_index);
+    ret->num_layers = GET_BE_WORD(record->num_layers);
 
-    layer = (struct COLR_LayerRecord*)((BYTE*)colr + layerrecordoffset) + ret->first_layer + ret->layer;
-    ret->glyph = GET_BE_WORD(layer->GID);
-    ret->palette_index = GET_BE_WORD(layer->paletteIndex);
+    if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records),
+            (ret->first_layer + ret->layer) * sizeof(*layer))))
+    {
+        layer += ret->first_layer + ret->layer;
+        ret->glyph = GET_BE_WORD(layer->glyph);
+        ret->palette_index = GET_BE_WORD(layer->palette_index);
+    }
 
     return S_OK;
 }
 
-void opentype_colr_next_glyph(const void *colr, struct dwrite_colorglyph *glyph)
+void opentype_colr_next_glyph(const struct dwrite_fonttable *colr, struct dwrite_colorglyph *glyph)
 {
-    const struct COLR_Header *header = colr;
-    const struct COLR_LayerRecord *layer;
-    DWORD layerrecordoffset = GET_BE_DWORD(header->offsetLayerRecord);
+    const struct colr_layer_record *layer;
+    const struct colr_header *header;
 
     /* iterated all the way through */
     if (glyph->layer == glyph->num_layers)
         return;
 
+    if (!(header = table_read_ensure(colr, 0, sizeof(*header))))
+        return;
+
     glyph->layer++;
-    layer = (struct COLR_LayerRecord*)((BYTE*)colr + layerrecordoffset) + glyph->first_layer + glyph->layer;
-    glyph->glyph = GET_BE_WORD(layer->GID);
-    glyph->palette_index = GET_BE_WORD(layer->paletteIndex);
+
+    if ((layer = table_read_ensure(colr, GET_BE_DWORD(header->offset_layer_records),
+            (glyph->first_layer + glyph->layer) * sizeof(*layer))))
+    {
+        layer += glyph->first_layer + glyph->layer;
+        glyph->glyph = GET_BE_WORD(layer->glyph);
+        glyph->palette_index = GET_BE_WORD(layer->palette_index);
+    }
 }
 
 BOOL opentype_has_vertical_variants(IDWriteFontFace4 *fontface)
-- 
2.20.1




More information about the wine-devel mailing list