dwrite: Validate 'VDMX' data before using it.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f73ba331c1
commit
2ca9aa16b2
|
@ -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_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_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 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_palettecount(const struct dwrite_fonttable *table) DECLSPEC_HIDDEN;
|
||||||
extern unsigned int opentype_get_cpal_paletteentrycount(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,
|
extern HRESULT opentype_get_cpal_entries(const struct dwrite_fonttable *table, unsigned int palette,
|
||||||
|
|
|
@ -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;
|
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)
|
static const struct dwrite_fonttable *get_fontface_gasp(struct dwrite_fontface *fontface)
|
||||||
|
|
|
@ -343,14 +343,14 @@ typedef struct {
|
||||||
TT_NameRecord nameRecord[1];
|
TT_NameRecord nameRecord[1];
|
||||||
} TT_NAME_V0;
|
} TT_NAME_V0;
|
||||||
|
|
||||||
struct VDMX_Header
|
struct vdmx_header
|
||||||
{
|
{
|
||||||
WORD version;
|
WORD version;
|
||||||
WORD numRecs;
|
WORD num_recs;
|
||||||
WORD numRatios;
|
WORD num_ratios;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VDMX_Ratio
|
struct vdmx_ratio
|
||||||
{
|
{
|
||||||
BYTE bCharSet;
|
BYTE bCharSet;
|
||||||
BYTE xRatio;
|
BYTE xRatio;
|
||||||
|
@ -358,20 +358,21 @@ struct VDMX_Ratio
|
||||||
BYTE yEndRatio;
|
BYTE yEndRatio;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VDMX_group
|
struct vdmx_vtable
|
||||||
{
|
|
||||||
WORD recs;
|
|
||||||
BYTE startsz;
|
|
||||||
BYTE endsz;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VDMX_vTable
|
|
||||||
{
|
{
|
||||||
WORD yPelHeight;
|
WORD yPelHeight;
|
||||||
SHORT yMax;
|
SHORT yMax;
|
||||||
SHORT yMin;
|
SHORT yMin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vdmx_group
|
||||||
|
{
|
||||||
|
WORD recs;
|
||||||
|
BYTE startsz;
|
||||||
|
BYTE endsz;
|
||||||
|
struct vdmx_vtable entries[1];
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CHAR FeatureTag[4];
|
CHAR FeatureTag[4];
|
||||||
WORD Feature;
|
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;
|
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;
|
WORD num_ratios, i;
|
||||||
struct VDMX_Ratio *ratios = (struct VDMX_Ratio*)(hdr + 1);
|
const struct vdmx_ratio *ratios = (struct vdmx_ratio *)(hdr + 1);
|
||||||
BYTE dev_x_ratio = 1, dev_y_ratio = 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++) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (group_offset)
|
|
||||||
return (const struct VDMX_group *)((BYTE *)hdr + group_offset);
|
return group_offset;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
unsigned int num_ratios, num_recs, group_offset, i;
|
||||||
const struct VDMX_group *group;
|
const struct vdmx_header *header;
|
||||||
const struct VDMX_vTable *tables;
|
const struct vdmx_group *group;
|
||||||
WORD recs, i;
|
|
||||||
|
|
||||||
if (!data)
|
if (!vdmx->exists)
|
||||||
return FALSE;
|
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)
|
if (!group)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
recs = GET_BE_WORD(group->recs);
|
if (emsize < group->startsz || emsize >= group->endsz)
|
||||||
if (emsize < group->startsz || emsize >= group->endsz) return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
tables = (const struct VDMX_vTable *)(group + 1);
|
for (i = 0; i < num_recs; ++i)
|
||||||
for (i = 0; i < recs; i++) {
|
{
|
||||||
WORD ppem = GET_BE_WORD(tables[i].yPelHeight);
|
WORD ppem = GET_BE_WORD(group->entries[i].yPelHeight);
|
||||||
if (ppem > emsize) {
|
if (ppem > emsize) {
|
||||||
FIXME("interpolate %d\n", emsize);
|
FIXME("interpolate %d\n", emsize);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ppem == emsize) {
|
if (ppem == emsize) {
|
||||||
*ascent = (SHORT)GET_BE_WORD(tables[i].yMax);
|
*ascent = (SHORT)GET_BE_WORD(group->entries[i].yMax);
|
||||||
*descent = -(SHORT)GET_BE_WORD(tables[i].yMin);
|
*descent = -(SHORT)GET_BE_WORD(group->entries[i].yMin);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue