From 9597fd7b40179d7411b4a7443f2bc4cad8c4dfdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Thu, 11 Nov 2021 17:33:37 +0200 Subject: [PATCH] [sfnt] Avoid undefined shifts in `COLR` v1 paint parsing * src/sfnt/ttcolr.c (read_paint, tt_face_get_paint): Tighten shift behavior by using multiplication, mostly using macros from ftcalc.h. Fixes: https://bugs.chromium.org/p/chromium/issues/detail?id=1269168 --- src/sfnt/ttcolr.c | 67 ++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c index deec80b9b..8f5cc8bcd 100644 --- a/src/sfnt/ttcolr.c +++ b/src/sfnt/ttcolr.c @@ -27,6 +27,7 @@ */ +#include #include #include #include @@ -509,12 +510,12 @@ * In order to support variations expose these as FT_Fixed 16.16 values so * that we can support fractional values after interpolation. */ - apaint->u.linear_gradient.p0.x = FT_NEXT_SHORT( p ) << 16; - apaint->u.linear_gradient.p0.y = FT_NEXT_SHORT( p ) << 16; - apaint->u.linear_gradient.p1.x = FT_NEXT_SHORT( p ) << 16; - apaint->u.linear_gradient.p1.y = FT_NEXT_SHORT( p ) << 16; - apaint->u.linear_gradient.p2.x = FT_NEXT_SHORT( p ) << 16; - apaint->u.linear_gradient.p2.y = FT_NEXT_SHORT( p ) << 16; + apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); return 1; } @@ -525,13 +526,13 @@ &apaint->u.radial_gradient.colorline ) ) return 0; - apaint->u.radial_gradient.c0.x = FT_NEXT_SHORT( p ) << 16; - apaint->u.radial_gradient.c0.y = FT_NEXT_SHORT( p ) << 16; + apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.radial_gradient.r0 = FT_NEXT_USHORT( p ) << 16; - apaint->u.radial_gradient.c1.x = FT_NEXT_SHORT( p ) << 16; - apaint->u.radial_gradient.c1.y = FT_NEXT_SHORT( p ) << 16; + apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); apaint->u.radial_gradient.r1 = FT_NEXT_USHORT( p ) << 16; @@ -544,11 +545,15 @@ &apaint->u.sweep_gradient.colorline ) ) return 0; - apaint->u.sweep_gradient.center.x = FT_NEXT_SHORT( p ) << 16; - apaint->u.sweep_gradient.center.y = FT_NEXT_SHORT( p ) << 16; + apaint->u.sweep_gradient.center.x = + INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.sweep_gradient.center.y = + INT_TO_FIXED( FT_NEXT_SHORT( p ) ); - apaint->u.sweep_gradient.start_angle = FT_NEXT_SHORT( p ) << 2; - apaint->u.sweep_gradient.end_angle = FT_NEXT_SHORT( p ) << 2; + apaint->u.sweep_gradient.start_angle = + F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.sweep_gradient.end_angle = + F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); return 1; } @@ -591,8 +596,8 @@ apaint->u.translate.paint.p = child_table_p; apaint->u.translate.paint.insert_root_transform = 0; - apaint->u.translate.dx = FT_NEXT_SHORT( p ) << 16; - apaint->u.translate.dy = FT_NEXT_SHORT( p ) << 16; + apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); return 1; } @@ -610,14 +615,14 @@ apaint->u.scale.paint.insert_root_transform = 0; /* All scale paints get at least one scale value. */ - apaint->u.scale.scale_x = FT_NEXT_SHORT( p ) << 2; + apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); /* Non-uniform ones read an extra y value. */ if ( apaint->format == FT_COLR_PAINTFORMAT_SCALE || (FT_PaintFormat_Internal)apaint->format == FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER ) - apaint->u.scale.scale_y = FT_NEXT_SHORT( p ) << 2; + apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); else apaint->u.scale.scale_y = apaint->u.scale.scale_x; @@ -628,8 +633,8 @@ (FT_PaintFormat_Internal)apaint->format == FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER ) { - apaint->u.scale.center_x = FT_NEXT_SHORT ( p ) << 16; - apaint->u.scale.center_y = FT_NEXT_SHORT ( p ) << 16; + apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); + apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); } else { @@ -651,17 +656,13 @@ apaint->u.rotate.paint.p = child_table_p; apaint->u.rotate.paint.insert_root_transform = 0; - /* The angle is specified as F2DOT14 and our output type is an FT_Fixed, - * shift by 2 positions. */ - apaint->u.rotate.angle = FT_NEXT_SHORT( p ) << 2; + apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); if ( (FT_PaintFormat_Internal)apaint->format == FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER ) { - /* The center is specified as Int16 in font units, shift by 16 bits to - * convert to our FT_Fixed output type. */ - apaint->u.rotate.center_x = FT_NEXT_SHORT( p ) << 16; - apaint->u.rotate.center_y = FT_NEXT_SHORT( p ) << 16; + apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); } else { @@ -681,14 +682,14 @@ apaint->u.skew.paint.p = child_table_p; apaint->u.skew.paint.insert_root_transform = 0; - apaint->u.skew.x_skew_angle = FT_NEXT_SHORT( p ) << 2; - apaint->u.skew.y_skew_angle = FT_NEXT_SHORT( p ) << 2; + apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); if ( (FT_PaintFormat_Internal)apaint->format == FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER ) { - apaint->u.skew.center_x = FT_NEXT_SHORT( p ) << 16; - apaint->u.skew.center_y = FT_NEXT_SHORT( p ) << 16; + apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); } else { @@ -1094,9 +1095,9 @@ if ( face->root.internal->transform_flags & 2 ) { paint->u.transform.affine.dx = - face->root.internal->transform_delta.x << 10; + face->root.internal->transform_delta.x * ( 1 << 10 ); paint->u.transform.affine.dy = - face->root.internal->transform_delta.y << 10; + face->root.internal->transform_delta.y * ( 1 << 10 ); } else {