From a34afe6786cfd9fb129d7d0be1e8fa92268a2c46 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sat, 12 Jun 2021 08:40:16 +0200 Subject: [PATCH] [psaux] Fix assertions. * src/psaux/pshints.c (cf2_hintmap_adjustHints): Check for overflow before emitting an assertion error. --- ChangeLog | 7 +++++++ src/psaux/pshints.c | 45 ++++++++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index e23603996..02fc1a5f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2021-06-12 Werner Lemberg + + [psaux] Fix assertions. + + * src/psaux/pshints.c (cf2_hintmap_adjustHints): Check for overflow + before emitting an assertion error. + 2021-06-09 Alexei Podtelezhnikov * src/truetype/ttinterp.c (TT_RunIns): Optimize tracing. diff --git a/src/psaux/pshints.c b/src/psaux/pshints.c index f6e6dd55b..ad472c98d 100644 --- a/src/psaux/pshints.c +++ b/src/psaux/pshints.c @@ -412,6 +412,12 @@ { FT_Bool isPair = cf2_hint_isPair( &hintmap->edge[i] ); + /* final amount to move edge or edge pair */ + CF2_Fixed move = 0; + + CF2_Fixed dsCoord_i; + CF2_Fixed dsCoord_j; + /* index of upper edge (same value for ghost hint) */ j = isPair ? i + 1 : i; @@ -422,11 +428,14 @@ FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) == cf2_hint_isLocked( &hintmap->edge[j] ) ); + dsCoord_i = hintmap->edge[i].dsCoord; + dsCoord_j = hintmap->edge[j].dsCoord; + if ( !cf2_hint_isLocked( &hintmap->edge[i] ) ) { /* hint edge is not locked, we can adjust it */ - CF2_Fixed fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord ); - CF2_Fixed fracUp = cf2_fixedFraction( hintmap->edge[j].dsCoord ); + CF2_Fixed fracDown = cf2_fixedFraction( dsCoord_i ); + CF2_Fixed fracUp = cf2_fixedFraction( dsCoord_j ); /* calculate all four possibilities; moves down are negative */ CF2_Fixed downMoveDown = 0 - fracDown; @@ -443,9 +452,6 @@ /* smallest move down */ CF2_Fixed moveDown = FT_MAX( downMoveDown, upMoveDown ); - /* final amount to move edge or edge pair */ - CF2_Fixed move; - CF2_Fixed downMinCounter = CF2_MIN_COUNTER; CF2_Fixed upMinCounter = CF2_MIN_COUNTER; FT_Bool saveEdge = FALSE; @@ -467,16 +473,14 @@ /* is there room to move up? */ /* there is if we are at top of array or the next edge is at or */ /* beyond proposed move up? */ - if ( j >= hintmap->count - 1 || + if ( j >= hintmap->count - 1 || hintmap->edge[j + 1].dsCoord >= - ADD_INT32( hintmap->edge[j].dsCoord, - moveUp + upMinCounter ) ) + ADD_INT32( dsCoord_j, moveUp + upMinCounter ) ) { /* there is room to move up; is there also room to move down? */ - if ( i == 0 || + if ( i == 0 || hintmap->edge[i - 1].dsCoord <= - ADD_INT32( hintmap->edge[i].dsCoord, - moveDown - downMinCounter ) ) + ADD_INT32( dsCoord_i, moveDown - downMinCounter ) ) { /* move smaller absolute amount */ move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */ @@ -487,10 +491,9 @@ else { /* is there room to move down? */ - if ( i == 0 || + if ( i == 0 || hintmap->edge[i - 1].dsCoord <= - ADD_INT32( hintmap->edge[i].dsCoord, - moveDown - downMinCounter ) ) + ADD_INT32( dsCoord_i, moveDown - downMinCounter ) ) { move = moveDown; /* true if non-optimum move */ @@ -524,17 +527,21 @@ } /* move the edge(s) */ - hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord, - move ); + hintmap->edge[i].dsCoord = ADD_INT32( dsCoord_i, move ); if ( isPair ) - hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord, - move ); + hintmap->edge[j].dsCoord = ADD_INT32( dsCoord_j, move ); } - /* assert there are no overlaps in device space */ + /* assert there are no overlaps in device space; */ + /* ignore tests if there was overflow (that is, if */ + /* operands have the same sign but the sum does not) */ FT_ASSERT( i == 0 || + ( ( dsCoord_i ^ move ) >= 0 && + ( dsCoord_i ^ hintmap->edge[i].dsCoord ) < 0 ) || hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord ); FT_ASSERT( i < j || + ( ( dsCoord_j ^ move ) >= 0 && + ( dsCoord_j ^ hintmap->edge[j].dsCoord ) < 0 ) || hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord ); /* adjust the scales, avoiding divide by zero */