diff --git a/ChangeLog b/ChangeLog index dc8d79b6b..77b2bc705 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2014-09-03 Alexei Podtelezhnikov + + [base] Tighten the overflow check in `FT_DivFix'. + + This fixes a 13-year old bug. The original overflow check should have + been updated when rounding was introduced into this function + (c2cd00443b). + + * src/base/ftcalc.c (FT_DivFix) [!FT_LONG64]: Updated. + * include/freetype.h (FT_DivFix): Updated documentation. + 2014-09-03 Alexei Podtelezhnikov [base] Tighten the overflow check in `FT_MulFix'. diff --git a/include/freetype.h b/include/freetype.h index 1ce138ccf..6a3150242 100644 --- a/include/freetype.h +++ b/include/freetype.h @@ -3807,18 +3807,12 @@ FT_BEGIN_HEADER /* used to divide a given value by a 16.16 fixed-point factor. */ /* */ /* */ - /* a :: The first multiplier. */ - /* b :: The second multiplier. Use a 16.16 factor here whenever */ - /* possible (see note below). */ + /* a :: The numerator. */ + /* b :: The denominator. Use a 16.16 factor here. */ /* */ /* */ /* The result of `(a*0x10000)/b'. */ /* */ - /* */ - /* The optimization for FT_DivFix() is simple: If (a~<<~16) fits in */ - /* 32~bits, then the division is computed directly. Otherwise, we */ - /* use a specialized version of @FT_MulDiv. */ - /* */ FT_EXPORT( FT_Long ) FT_DivFix( FT_Long a, FT_Long b ); diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c index 671eec874..723712ead 100644 --- a/src/base/ftcalc.c +++ b/src/base/ftcalc.c @@ -397,6 +397,13 @@ /* covers the practical range of use. The actual test below is a bit */ /* tighter to avoid the border case overflows. */ /* */ + /* In the case of FT_DivFix, the direct overflow check */ + /* */ + /* a << 16 <= X - c/2 */ + /* */ + /* is scaled down by 2^16 and we use */ + /* */ + /* a <= 65535 - (c >> 17) . */ /* documentation is in freetype.h */ @@ -593,7 +600,7 @@ /* check for division by 0 */ q = 0x7FFFFFFFL; } - else if ( ( a >> 16 ) == 0 ) + else if ( a <= 65535L - ( b >> 17 ) ) { /* compute result directly */ q = (FT_Long)( ( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / b );