[PATCH] gdi32: Clamp unsigned integers to 32-bit range when scaling fonts

Alex Henrie alexhenrie24 at gmail.com
Mon Dec 11 23:10:48 CST 2017


Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
Fixes test crash (floating point exception due to double value outside
of integer range) with TAMu_Kadampari.ttf from Arch Linux's
ttf-indic-otf package. sTypoLineGap is -194 in this font, and Windows 10
sets otmLineGap to 4294967295.

Also fixes the crash with GohaTibebZemen.otf from Arch's xorg-fonts-misc
package. sCapHeight and sxHeight are -32768 in this font, and Windows 10
refuses to install it. However, Windows XP installs the font without
complaint and sets otmsCapEmHeight and otmsXHeight to 4294966903. I
think the 0.00000009% difference from UINT_MAX is just rounding error.
---
 dlls/gdi32/freetype.c    | 11 ++++++-----
 dlls/gdi32/gdi_private.h |  7 +++++++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 7c5a7ef979..961f9e5f03 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -7578,19 +7578,20 @@ static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *
 
 #define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x))
 #define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y))
+#define SCALE_YU(y) (y) = GDI_ROUND_UINT((double)(y) * (scale_y))
 
     SCALE_Y(potm->otmAscent);
     SCALE_Y(potm->otmDescent);
-    SCALE_Y(potm->otmLineGap);
-    SCALE_Y(potm->otmsCapEmHeight);
-    SCALE_Y(potm->otmsXHeight);
+    SCALE_YU(potm->otmLineGap);
+    SCALE_YU(potm->otmsCapEmHeight);
+    SCALE_YU(potm->otmsXHeight);
     SCALE_Y(potm->otmrcFontBox.top);
     SCALE_Y(potm->otmrcFontBox.bottom);
     SCALE_X(potm->otmrcFontBox.left);
     SCALE_X(potm->otmrcFontBox.right);
     SCALE_Y(potm->otmMacAscent);
     SCALE_Y(potm->otmMacDescent);
-    SCALE_Y(potm->otmMacLineGap);
+    SCALE_YU(potm->otmMacLineGap);
     SCALE_X(potm->otmptSubscriptSize.x);
     SCALE_Y(potm->otmptSubscriptSize.y);
     SCALE_X(potm->otmptSubscriptOffset.x);
@@ -7599,7 +7600,7 @@ static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *
     SCALE_Y(potm->otmptSuperscriptSize.y);
     SCALE_X(potm->otmptSuperscriptOffset.x);
     SCALE_Y(potm->otmptSuperscriptOffset.y);
-    SCALE_Y(potm->otmsStrikeoutSize);
+    SCALE_YU(potm->otmsStrikeoutSize);
     SCALE_Y(potm->otmsStrikeoutPosition);
     SCALE_Y(potm->otmsUnderscoreSize);
     SCALE_Y(potm->otmsUnderscorePosition);
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 4236aa3690..c591057e3a 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -141,6 +141,13 @@ static inline INT GDI_ROUND(double val)
    return (int)floor(val + 0.5);
 }
 
+static inline UINT GDI_ROUND_UINT(double val)
+{
+    double ret = floor(val + 0.5);
+    if (ret > UINT_MAX) return UINT_MAX;
+    return (UINT)ret;
+}
+
 #define GET_DC_PHYSDEV(dc,func) \
     get_physdev_entry_point( (dc)->physDev, FIELD_OFFSET(struct gdi_dc_funcs,func))
 
-- 
2.15.1




More information about the wine-devel mailing list