From 537c55d39d6636c93086780f03fba1f975a8299d Mon Sep 17 00:00:00 2001 From: Dave Arnold Date: Thu, 2 Oct 2014 06:32:32 +0200 Subject: [PATCH] [cff] Fix Savannah bug #43271. * src/cff/cf2font.c (cf2_computeDarkening): Change overflow detection to use logarithms and clamp `scaledStem'. --- ChangeLog | 7 +++++++ src/cff/cf2font.c | 38 +++++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1468429b0..aed178405 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2014-10-02 Dave Arnold + + [cff] Fix Savannah bug #43271. + + * src/cff/cf2font.c (cf2_computeDarkening): Change overflow + detection to use logarithms and clamp `scaledStem'. + 2014-10-01 Alexei Podtelezhnikov * src/base/ftcalc.c: Remove miscellaneous type casts. diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c index 6e99dc2f0..3d2c22a3b 100644 --- a/src/cff/cf2font.c +++ b/src/cff/cf2font.c @@ -105,6 +105,7 @@ /* adjusting for emRatio converts darkenAmount to character */ /* space (font units). */ CF2_Fixed stemWidthPer1000, scaledStem; + FT_Int logBase2; *darkenAmount = 0; @@ -131,25 +132,32 @@ /* convert from true character space to 1000 unit character space; */ /* add synthetic emboldening effect */ - /* we have to assure that the computation of `scaledStem' */ - /* and `stemWidthPer1000' don't overflow */ + /* `stemWidthPer1000' will not overflow for a legitimate font */ stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio ); - if ( emRatio > CF2_FIXED_ONE && - stemWidthPer1000 <= ( stemWidth + boldenAmount ) ) - { - stemWidthPer1000 = 0; /* to pacify compiler */ - scaledStem = cf2_intToFixed( x4 ); - } - else - { - scaledStem = FT_MulFix( stemWidthPer1000, ppem ); + /* `scaledStem' can easily overflow, so we must clamp its maximum */ + /* value; the test doesn't need to be precise, but must be */ + /* conservative. The clamp value (default 2333) where */ + /* `darkenAmount' is zero is well below the overflow value of */ + /* 32767. */ + /* */ + /* FT_MSB computes the integer part of the base 2 logarithm. The */ + /* number of bits for the product is 1 or 2 more than the sum of */ + /* logarithms; remembering that the 16 lowest bits of the fraction */ + /* are dropped this is correct to within a factor of almost 4. */ + /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and */ + /* is flagged as possible overflow because 0xff.ffff * 0xff.ffff = */ + /* 0xffff.fe00 is also 23+23. */ - if ( ppem > CF2_FIXED_ONE && - scaledStem <= stemWidthPer1000 ) - scaledStem = cf2_intToFixed( x4 ); - } + logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) + + FT_MSB( (FT_UInt32)ppem ); + + if ( logBase2 >= 46 ) + /* possible overflow */ + scaledStem = cf2_intToFixed( x4 ); + else + scaledStem = FT_MulFix( stemWidthPer1000, ppem ); /* now apply the darkening parameters */