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

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


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h |  3 ++
 dlls/dwrite/font.c           |  2 +-
 dlls/dwrite/opentype.c       | 63 +++++++++++++++++++-----------------
 dlls/dwrite/tests/font.c     |  2 +-
 4 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 3251e66dec..2d20b41ea6 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -216,6 +216,9 @@ struct dwrite_fonttable
     BOOL exists;
 };
 
+extern const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag,
+        struct dwrite_fonttable *table) DECLSPEC_HIDDEN;
+
 extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,BOOL*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,UINT32*) DECLSPEC_HIDDEN;
 extern HRESULT opentype_get_font_table(struct file_stream_desc*,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN;
 extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *table, unsigned int max_count,
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index bb04df6bd2..372578ec48 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -338,7 +338,7 @@ static HRESULT set_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16
     return S_OK;
 }
 
-static const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag, struct dwrite_fonttable *table)
+const void* get_fontface_table(IDWriteFontFace4 *fontface, UINT32 tag, struct dwrite_fonttable *table)
 {
     HRESULT hr;
 
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 82491dcc02..261d00c8a8 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -268,17 +268,19 @@ typedef struct {
     WORD numGlyphs;
 } maxp;
 
-typedef struct {
-    WORD majorVersion;
-    WORD minorVersion;
-    DWORD numSizes;
-} CBLCHeader;
+struct cblc_header
+{
+    WORD major_version;
+    WORD minor_version;
+    DWORD num_sizes;
+};
 
 typedef struct {
     BYTE res[12];
 } sbitLineMetrics;
 
-typedef struct {
+struct cblc_bitmapsize_table
+{
     DWORD indexSubTableArrayOffset;
     DWORD indexTablesSize;
     DWORD numberofIndexSubTables;
@@ -289,9 +291,9 @@ typedef struct {
     WORD endGlyphIndex;
     BYTE ppemX;
     BYTE ppemY;
-    BYTE bitDepth;
+    BYTE bit_depth;
     BYTE flags;
-} CBLCBitmapSizeTable;
+};
 
 struct gasp_range
 {
@@ -2284,36 +2286,39 @@ static DWORD opentype_get_sbix_formats(IDWriteFontFace4 *fontface)
     return ret;
 }
 
-static UINT32 opentype_get_cblc_formats(IDWriteFontFace4 *fontface)
+static unsigned int opentype_get_cblc_formats(IDWriteFontFace4 *fontface)
 {
-    CBLCBitmapSizeTable *sizes;
-    UINT32 num_sizes, size, s;
-    BOOL exists = FALSE;
-    CBLCHeader *header;
-    UINT32 ret = 0;
-    void *context;
-    HRESULT hr;
+    const unsigned int format_mask = DWRITE_GLYPH_IMAGE_FORMATS_PNG |
+            DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8;
+    const struct cblc_bitmapsize_table *sizes;
+    struct dwrite_fonttable cblc = { 0 };
+    unsigned int num_sizes, i, ret = 0;
+    const struct cblc_header *header;
 
-    if (FAILED(hr = IDWriteFontFace4_TryGetFontTable(fontface, MS_CBLC_TAG, (const void **)&header, &size,
-            &context, &exists)))
+    cblc.exists = TRUE;
+    if (!get_fontface_table(fontface, MS_CBLC_TAG, &cblc))
         return 0;
 
-    if (!exists)
-        return 0;
+    num_sizes = table_read_be_dword(&cblc, FIELD_OFFSET(struct cblc_header, num_sizes));
+    sizes = table_read_ensure(&cblc, sizeof(*header), num_sizes * sizeof(*sizes));
 
-    num_sizes = GET_BE_DWORD(header->numSizes);
-    sizes = (CBLCBitmapSizeTable *)(header + 1);
+    if (sizes)
+    {
+        for (i = 0; i < num_sizes; ++i)
+        {
+            BYTE bpp = sizes[i].bit_depth;
 
-    for (s = 0; s < num_sizes; s++) {
-        BYTE bpp = sizes->bitDepth;
+            if ((ret & format_mask) == format_mask)
+                break;
 
-        if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8)
-            ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
-        else if (bpp == 32)
-            ret |= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8;
+            if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8)
+                ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
+            else if (bpp == 32)
+                ret |= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8;
+        }
     }
 
-    IDWriteFontFace4_ReleaseFontTable(fontface, context);
+    IDWriteFontFace4_ReleaseFontTable(fontface, cblc.context);
 
     return ret;
 }
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 3e736c82b7..309c0a2b08 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -8755,7 +8755,7 @@ static DWORD get_cblc_formats(IDWriteFontFace4 *fontface)
     sizes = (CBLCBitmapSizeTable *)(header + 1);
 
     for (s = 0; s < num_sizes; s++) {
-        BYTE bpp = sizes->bitDepth;
+        BYTE bpp = sizes[s].bitDepth;
 
         if (bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8)
             ret |= DWRITE_GLYPH_IMAGE_FORMATS_PNG;
-- 
2.20.1




More information about the wine-devel mailing list