Commit a34afe6786cfd9fb129d7d0be1e8fa92268a2c46

Werner Lemberg 2021-06-12T08:40:16

[psaux] Fix assertions. * src/psaux/pshints.c (cf2_hintmap_adjustHints): Check for overflow before emitting an assertion error.

diff --git a/ChangeLog b/ChangeLog
index e236039..02fc1a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2021-06-12  Werner Lemberg  <wl@gnu.org>
+
+	[psaux] Fix assertions.
+
+	* src/psaux/pshints.c (cf2_hintmap_adjustHints): Check for overflow
+	before emitting an assertion error.
+
 2021-06-09  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	* src/truetype/ttinterp.c (TT_RunIns): Optimize tracing. 
diff --git a/src/psaux/pshints.c b/src/psaux/pshints.c
index f6e6dd5..ad472c9 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 */