Nikolay Sivov : dwrite: Validate 'sbix' data before using it.

Alexandre Julliard julliard at winehq.org
Tue Jan 29 15:18:15 CST 2019


Module: wine
Branch: master
Commit: f73ba331c18577942a371b98a724f2a44f6565ca
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=f73ba331c18577942a371b98a724f2a44f6565ca

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Jan 29 10:06:44 2019 +0300

dwrite: Validate 'sbix' data before using it.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dwrite/opentype.c | 125 +++++++++++++++++++++++++++----------------------
 1 file changed, 68 insertions(+), 57 deletions(-)

diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 261d00c..35cf838 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -243,30 +243,34 @@ typedef struct {
     USHORT numberOfHMetrics;
 } TT_HHEA;
 
-typedef struct {
+struct sbix_header
+{
     WORD version;
     WORD flags;
-    DWORD numStrikes;
-    DWORD strikeOffset[1];
-} sbix_header;
+    DWORD num_strikes;
+    DWORD strike_offset[1];
+};
 
-typedef struct {
+struct sbix_strike
+{
     WORD ppem;
     WORD ppi;
-    DWORD glyphDataOffsets[1];
-} sbix_strike;
+    DWORD glyphdata_offsets[1];
+};
 
-typedef struct {
+struct sbix_glyph_data
+{
     WORD originOffsetX;
     WORD originOffsetY;
-    DWORD graphicType;
+    DWORD graphic_type;
     BYTE data[1];
-} sbix_glyph_data;
+};
 
-typedef struct {
+struct maxp
+{
     DWORD version;
-    WORD numGlyphs;
-} maxp;
+    WORD num_glyphs;
+};
 
 struct cblc_header
 {
@@ -2221,67 +2225,74 @@ static BOOL opentype_has_font_table(IDWriteFontFace4 *fontface, UINT32 tag)
     return exists;
 }
 
-static DWORD opentype_get_sbix_formats(IDWriteFontFace4 *fontface)
+static unsigned int opentype_get_sbix_formats(IDWriteFontFace4 *fontface)
 {
-    UINT32 size, s, num_strikes;
-    const sbix_header *header;
-    UINT16 g, num_glyphs;
-    BOOL exists = FALSE;
-    const maxp *maxp;
-    const void *data;
-    DWORD ret = 0;
-    void *context;
-    HRESULT hr;
+    unsigned int num_strikes, num_glyphs, i, j, ret = 0;
+    const struct sbix_header *sbix_header;
+    struct dwrite_fonttable table;
 
-    hr = IDWriteFontFace4_TryGetFontTable(fontface, MS_MAXP_TAG, &data, &size, &context, &exists);
-    if (FAILED(hr) || !exists)
+    memset(&table, 0, sizeof(table));
+    table.exists = TRUE;
+
+    if (!get_fontface_table(fontface, MS_MAXP_TAG, &table))
         return 0;
 
-    maxp = data;
-    num_glyphs = GET_BE_WORD(maxp->numGlyphs);
+    num_glyphs = table_read_be_word(&table, FIELD_OFFSET(struct maxp, num_glyphs));
 
-    IDWriteFontFace4_ReleaseFontTable(fontface, context);
+    IDWriteFontFace4_ReleaseFontTable(fontface, table.context);
 
-    if (FAILED(IDWriteFontFace4_TryGetFontTable(fontface, MS_SBIX_TAG, &data, &size, &context, &exists))) {
-        WARN("Failed to get 'sbix' table, %#x\n", hr);
-        return 0;
-    }
+    memset(&table, 0, sizeof(table));
+    table.exists = TRUE;
 
-    header = data;
-    num_strikes = GET_BE_DWORD(header->numStrikes);
+    if (!get_fontface_table(fontface, MS_SBIX_TAG, &table))
+        return 0;
 
-    for (s = 0; s < num_strikes; s++) {
-        sbix_strike *strike = (sbix_strike *)((BYTE *)header + GET_BE_DWORD(header->strikeOffset[s]));
+    num_strikes = table_read_be_dword(&table, FIELD_OFFSET(struct sbix_header, num_strikes));
+    sbix_header = table_read_ensure(&table, 0, FIELD_OFFSET(struct sbix_header, strike_offset[num_strikes]));
 
-        for (g = 0; g < num_glyphs; g++) {
-            DWORD offset = GET_BE_DWORD(strike->glyphDataOffsets[g]);
-            DWORD offset_next = GET_BE_DWORD(strike->glyphDataOffsets[g + 1]);
-            sbix_glyph_data *glyph_data;
-            DWORD format;
+    if (sbix_header)
+    {
+        for (i = 0; i < num_strikes; ++i)
+        {
+            unsigned int strike_offset = GET_BE_DWORD(sbix_header->strike_offset[i]);
+            const struct sbix_strike *strike = table_read_ensure(&table, strike_offset,
+                    FIELD_OFFSET(struct sbix_strike, glyphdata_offsets[num_glyphs + 1]));
 
-            if (offset == offset_next)
+            if (!strike)
                 continue;
 
-            glyph_data = (sbix_glyph_data *)((BYTE *)strike + offset);
-            switch (format = glyph_data->graphicType)
+            for (j = 0; j < num_glyphs; j++)
             {
-            case MS_PNG__TAG:
-                ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
-                break;
-            case MS_JPG__TAG:
-                ret |= DWRITE_GLYPH_IMAGE_FORMATS_JPEG;
-                break;
-            case MS_TIFF_TAG:
-                ret |= DWRITE_GLYPH_IMAGE_FORMATS_TIFF;
-                break;
-            default:
-                format = GET_BE_DWORD(format);
-                FIXME("unexpected bitmap format %s\n", debugstr_an((char *)&format, 4));
+                unsigned int offset = GET_BE_DWORD(strike->glyphdata_offsets[j]);
+                unsigned int next_offset = GET_BE_DWORD(strike->glyphdata_offsets[j + 1]);
+                const struct sbix_glyph_data *glyph_data;
+
+                if (offset == next_offset)
+                    continue;
+
+                glyph_data = table_read_ensure(&table, strike_offset + offset, sizeof(*glyph_data));
+                if (!glyph_data)
+                    continue;
+
+                switch (glyph_data->graphic_type)
+                {
+                    case MS_PNG__TAG:
+                        ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
+                        break;
+                    case MS_JPG__TAG:
+                        ret |= DWRITE_GLYPH_IMAGE_FORMATS_JPEG;
+                        break;
+                    case MS_TIFF_TAG:
+                        ret |= DWRITE_GLYPH_IMAGE_FORMATS_TIFF;
+                        break;
+                    default:
+                        FIXME("unexpected bitmap format %s\n", debugstr_tag(GET_BE_DWORD(glyph_data->graphic_type)));
+                }
             }
         }
     }
 
-    IDWriteFontFace4_ReleaseFontTable(fontface, context);
+    IDWriteFontFace4_ReleaseFontTable(fontface, table.context);
 
     return ret;
 }




More information about the wine-cvs mailing list