Nikolay Sivov : dwrite: Validate 'gasp' data before accessing it.

Alexandre Julliard julliard at winehq.org
Mon Jan 28 16:17:00 CST 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Jan 27 08:55:26 2019 +0300

dwrite: Validate 'gasp' data before accessing it.

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

---

 dlls/dwrite/dwrite_private.h |  2 +-
 dlls/dwrite/font.c           | 42 +++++++++++++++++-------------------------
 dlls/dwrite/opentype.c       | 43 ++++++++++++++++++++++++++++++++-----------
 3 files changed, 50 insertions(+), 37 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 52e7a18..9f8c941 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -254,7 +254,7 @@ enum gasp_flags {
     GASP_SYMMETRIC_SMOOTHING = 0x0008,
 };
 
-extern WORD opentype_get_gasp_flags(const WORD*,UINT32,INT) DECLSPEC_HIDDEN;
+extern unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp, float emsize) DECLSPEC_HIDDEN;
 
 /* BiDi helpers */
 extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 5c287ea..5c0b2a4 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -379,11 +379,10 @@ static const void* get_fontface_vdmx(struct dwrite_fontface *fontface)
     return get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_VDMX_TAG, &fontface->vdmx);
 }
 
-static const void* get_fontface_gasp(struct dwrite_fontface *fontface, UINT32 *size)
+static const struct dwrite_fonttable *get_fontface_gasp(struct dwrite_fontface *fontface)
 {
-    const void *ptr = get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_GASP_TAG, &fontface->gasp);
-    *size = fontface->gasp.size;
-    return ptr;
+    get_fontface_table(&fontface->IDWriteFontFace4_iface, MS_GASP_TAG, &fontface->gasp);
+    return &fontface->gasp;
 }
 
 static const void* get_fontface_cpal(struct dwrite_fontface *fontface)
@@ -687,7 +686,7 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace4 *iface,
 }
 
 static DWRITE_RENDERING_MODE fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring,
-    FLOAT ppem, WORD gasp)
+        float ppem, unsigned int gasp)
 {
     DWRITE_RENDERING_MODE mode = DWRITE_RENDERING_MODE_DEFAULT;
 
@@ -718,10 +717,8 @@ static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace
     FLOAT ppdip, DWRITE_MEASURING_MODE measuring, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *mode)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
-    const WORD *ptr;
-    UINT32 size;
+    unsigned int flags;
     FLOAT ppem;
-    WORD gasp;
 
     TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This, emSize, ppdip, measuring, params, mode);
 
@@ -741,9 +738,8 @@ static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace
         return S_OK;
     }
 
-    ptr = get_fontface_gasp(This, &size);
-    gasp = opentype_get_gasp_flags(ptr, size, ppem);
-    *mode = fontface_renderingmode_from_measuringmode(measuring, ppem, gasp);
+    flags = opentype_get_gasp_flags(get_fontface_gasp(This), ppem);
+    *mode = fontface_renderingmode_from_measuringmode(measuring, ppem, flags);
     return S_OK;
 }
 
@@ -1097,10 +1093,8 @@ static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFac
     DWRITE_GRID_FIT_MODE *gridfitmode)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
+    unsigned int flags;
     FLOAT emthreshold;
-    const WORD *ptr;
-    UINT32 size;
-    WORD gasp;
 
     TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This, emSize, dpiX, dpiY, m, is_sideways, threshold,
         measuringmode, params, renderingmode, gridfitmode);
@@ -1131,14 +1125,13 @@ static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFac
 
     emthreshold = threshold == DWRITE_OUTLINE_THRESHOLD_ANTIALIASED ? RECOMMENDED_OUTLINE_AA_THRESHOLD : RECOMMENDED_OUTLINE_A_THRESHOLD;
 
-    ptr = get_fontface_gasp(This, &size);
-    gasp = opentype_get_gasp_flags(ptr, size, emSize);
+    flags = opentype_get_gasp_flags(get_fontface_gasp(This), emSize);
 
     if (*renderingmode == DWRITE_RENDERING_MODE_DEFAULT) {
         if (emSize >= emthreshold)
             *renderingmode = DWRITE_RENDERING_MODE_OUTLINE;
         else
-            *renderingmode = fontface_renderingmode_from_measuringmode(measuringmode, emSize, gasp);
+            *renderingmode = fontface_renderingmode_from_measuringmode(measuringmode, emSize, flags);
     }
 
     if (*gridfitmode == DWRITE_GRID_FIT_MODE_DEFAULT) {
@@ -1147,7 +1140,8 @@ static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFac
         else if (measuringmode == DWRITE_MEASURING_MODE_GDI_CLASSIC || measuringmode == DWRITE_MEASURING_MODE_GDI_NATURAL)
             *gridfitmode = DWRITE_GRID_FIT_MODE_ENABLED;
         else
-            *gridfitmode = (gasp & (GASP_GRIDFIT|GASP_SYMMETRIC_GRIDFIT)) ? DWRITE_GRID_FIT_MODE_ENABLED : DWRITE_GRID_FIT_MODE_DISABLED;
+            *gridfitmode = flags & (GASP_GRIDFIT|GASP_SYMMETRIC_GRIDFIT) ?
+                    DWRITE_GRID_FIT_MODE_ENABLED : DWRITE_GRID_FIT_MODE_DISABLED;
     }
 
     return S_OK;
@@ -1229,10 +1223,8 @@ static HRESULT WINAPI dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFac
     IDWriteRenderingParams *params, DWRITE_RENDERING_MODE1 *rendering_mode, DWRITE_GRID_FIT_MODE *gridfit_mode)
 {
     struct dwrite_fontface *This = impl_from_IDWriteFontFace4(iface);
+    unsigned int flags;
     FLOAT emthreshold;
-    const WORD *ptr;
-    UINT32 size;
-    WORD gasp;
 
     TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This, emSize, dpiX, dpiY, m, is_sideways, threshold,
         measuring_mode, params, rendering_mode, gridfit_mode);
@@ -1263,14 +1255,13 @@ static HRESULT WINAPI dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFac
 
     emthreshold = threshold == DWRITE_OUTLINE_THRESHOLD_ANTIALIASED ? RECOMMENDED_OUTLINE_AA_THRESHOLD : RECOMMENDED_OUTLINE_A_THRESHOLD;
 
-    ptr = get_fontface_gasp(This, &size);
-    gasp = opentype_get_gasp_flags(ptr, size, emSize);
+    flags = opentype_get_gasp_flags(get_fontface_gasp(This), emSize);
 
     if (*rendering_mode == DWRITE_RENDERING_MODE1_DEFAULT) {
         if (emSize >= emthreshold)
             *rendering_mode = DWRITE_RENDERING_MODE1_OUTLINE;
         else
-            *rendering_mode = fontface_renderingmode_from_measuringmode(measuring_mode, emSize, gasp);
+            *rendering_mode = fontface_renderingmode_from_measuringmode(measuring_mode, emSize, flags);
     }
 
     if (*gridfit_mode == DWRITE_GRID_FIT_MODE_DEFAULT) {
@@ -1279,7 +1270,8 @@ static HRESULT WINAPI dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFac
         else if (measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL)
             *gridfit_mode = DWRITE_GRID_FIT_MODE_ENABLED;
         else
-            *gridfit_mode = (gasp & (GASP_GRIDFIT|GASP_SYMMETRIC_GRIDFIT)) ? DWRITE_GRID_FIT_MODE_ENABLED : DWRITE_GRID_FIT_MODE_DISABLED;
+            *gridfit_mode = flags & (GASP_GRIDFIT|GASP_SYMMETRIC_GRIDFIT) ?
+                    DWRITE_GRID_FIT_MODE_ENABLED : DWRITE_GRID_FIT_MODE_DISABLED;
     }
 
     return S_OK;
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 0e0de87..291b41b 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -292,6 +292,20 @@ typedef struct {
     BYTE bitDepth;
     BYTE flags;
 } CBLCBitmapSizeTable;
+
+struct gasp_range
+{
+    WORD max_ppem;
+    WORD flags;
+};
+
+struct gasp_header
+{
+    WORD version;
+    WORD num_ranges;
+    struct gasp_range ranges[1];
+};
+
 #include "poppack.h"
 
 enum OS2_FSSELECTION {
@@ -1959,25 +1973,32 @@ BOOL opentype_get_vdmx_size(const void *data, INT emsize, UINT16 *ascent, UINT16
     return FALSE;
 }
 
-WORD opentype_get_gasp_flags(const WORD *ptr, UINT32 size, INT emsize)
+unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp, float emsize)
 {
-    WORD num_recs, version;
+    unsigned int version, num_ranges, i;
+    const struct gasp_header *table;
     WORD flags = 0;
 
-    if (!ptr)
+    if (!gasp->exists)
         return 0;
 
-    version  = GET_BE_WORD( *ptr++ );
-    num_recs = GET_BE_WORD( *ptr++ );
-    if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD)) {
-        ERR("unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs);
+    num_ranges = table_read_be_word(gasp, FIELD_OFFSET(struct gasp_header, num_ranges));
+
+    table = table_read_ensure(gasp, 0, FIELD_OFFSET(struct gasp_header, ranges[num_ranges]));
+    if (!table)
+        return 0;
+
+    version = GET_BE_WORD(table->version);
+    if (version > 1)
+    {
+        ERR("Unsupported gasp table format version %u.\n", version);
         goto done;
     }
 
-    while (num_recs--) {
-        flags = GET_BE_WORD( *(ptr + 1) );
-        if (emsize <= GET_BE_WORD( *ptr )) break;
-        ptr += 2;
+    for (i = 0; i < num_ranges; ++i)
+    {
+        flags = GET_BE_WORD(table->ranges[i].flags);
+        if (emsize <= GET_BE_WORD(table->ranges[i].max_ppem)) break;
     }
 
 done:




More information about the wine-cvs mailing list