261c6956765a12f489c8f210e86d327f80173f5c
galt
  Fri Aug 21 19:25:56 2020 -0700
Fixes bug found by Jonathan during code review that can have infinite loop. Code is now a little simpler and more reliable. refs#26088

diff --git src/hg/lib/liftOver.c src/hg/lib/liftOver.c
index 6e65268..38f7a25 100644
--- src/hg/lib/liftOver.c
+++ src/hg/lib/liftOver.c
@@ -777,79 +777,74 @@
             int *pThickStart, int *pThickEnd, double minBlocks, bool fudgeThick,
             struct liftRange **retGood, struct liftRange **retBad, char **retError)
 /* Remap range list through chain.  Return error message on failure,
  * NULL on success. */
 {
 struct cBlock *b = chain->blockList;
 struct liftRange *r = *pRangeList, *nextR, *goodList = NULL, *badList = NULL;
 int bDiff, rStart = 0;
 bool gotStart = FALSE;
 int rCount = slCount(r), goodCount = 0;
 int thickStart = *pThickStart, thickEnd = *pThickEnd;
 int fudgeThickStart = 0, fudgeThickEnd = 0;
 bool gotThickStart = FALSE, gotThickEnd = FALSE;
 bool gotFudgeThickStart = FALSE;
 bool needThick = (thickStart != thickEnd);
-boolean done = FALSE;
 static char bErr[512];
 char *err = NULL;
 
 *pRangeList = NULL;
 if (r == NULL)
     {
     *retGood = *retBad = NULL;
     *retError = NULL;
     return;
     }
 if (b == NULL)
     {
     *retGood = NULL;
     *retBad = r;
     *retError = "Empty block list in intersecting chain";
     return;
     }
 nextR = r->next;
 for (;;)
     {
     /* Skip over chain blocks that end before range starts. */
-    while (b->tEnd <= r->start)
+    if (b->tEnd <= r->start)
 	{
 	b = b->next;
 	if (b == NULL)
 	    {
-	    done = TRUE;
 	    break;
 	    }
+        continue;
 	}
-    if (done) 
-	break;
 
     /* Put any range blocks that end before block starts on badList */
-    while (r->end <= b->tStart)
+    if (r->end <= b->tStart)
 	{
 	slAddHead(&badList, r);
 	r = nextR;
 	if (r == NULL)
 	    {
-	    done = TRUE;
 	    break;
 	    }
 	nextR = r->next;
 	gotStart = FALSE;
+        continue;
 	}
-    if (done) 
-	break;
 
     /* Map start and end of 'thick area' in a slightly picky fashion. */
     if (needThick)
 	{
 	if (b->tStart <= thickStart && thickStart < b->tEnd)
 	    {
 	    *pThickStart = thickStart + b->qStart - b->tStart;
 	    gotThickStart = TRUE;
 	    fudgeThickStart = *pThickStart;
 	    gotFudgeThickStart = TRUE;
 	    }
 	if (b->tStart <= thickEnd && thickEnd <= b->tEnd)
 	    {
 	    *pThickEnd = thickEnd + b->qStart - b->tStart;
 	    gotThickEnd = TRUE;
@@ -877,52 +872,45 @@
 	bDiff = b->qStart - b->tStart;
 	if (gotStart)
 	    {
 	    r->start = rStart;
 	    r->end += bDiff;
 	    slAddHead(&goodList, r);
 	    ++goodCount;
 	    }
 	else
 	    {
 	    slAddHead(&badList, r);
 	    }
 	r = nextR;
 	if (r == NULL)
 	    {
-	    done = TRUE;
 	    break;
 	    }
 	nextR = r->next;
 	gotStart = FALSE;
+	continue;
 	}
-    if (done) 
-	break;
 
-    // May have multiple small chain segments spanned by one exon, 
-    // so advance one exon if we are in the middle of a run, have start but no end yet.
-    if (b->tEnd < r->end && gotStart)
+    if (b->tEnd < r->end)
 	{
 	b = b->next;
 	if (b == NULL)
 	    {
-	    done = TRUE;
 	    break;
 	    }
 	}
-    if (done) 
-	break;
     }
 slReverse(&goodList);
 slReverse(&badList);
 if (needThick)
     {
     if (goodList != NULL && !gotFudgeThickStart)
 	fudgeThickStart = fudgeThickEnd = goodList->start;
     if (!gotThickStart)
 	{
 	if (fudgeThick)
 	    {
 	    if (goodList != NULL)
 		*pThickStart = fudgeThickStart;
 	    }
 	else