Nikolay Sivov : dwrite: Validate 'COLR' data before using it.
Alexandre Julliard
julliard at winehq.org
Tue Jan 29 15:18:15 CST 2019
Module: wine
Branch: master
Commit: 1ee968500348e2dcce6e1439bd47dffb5250d789
URL: https://source.winehq.org/git/wine.git/?a=commit;h=1ee968500348e2dcce6e1439bd47dffb5250d789
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue Jan 29 10:06:42 2019 +0300
dwrite: Validate 'COLR' data before using it.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 6eac1f4..3251e66 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 2c51674..bb04df6 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 647ac99..82491dc 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)
More information about the wine-cvs
mailing list