cec5ead054791f2a6601f308a56d280c08bd8ef7
braney
  Fri Sep 4 13:32:36 2026 -0700
quickLift: do not take the lift path on half a pair of settings

A hub can set quickLiftDb without setting quickLiftUrl, and nothing filters hub
trackDb settings.  The alignment loaders gated on quickLiftDb alone, so such a
stanza took the lift path with no chain file and hgTracks died in
endsWith(NULL, ".bb") from bigChainGetLinkFile, by way of quickLiftLoadChains.
Verified: SIGSEGV in strlen from common.c:1653, page truncated mid-HTML.  This is
reachable on a production browser now that bigChain and bigMaf are liftable,
because those carry their own bigDataUrl and so need no trustTrackDb.

quickLiftIsLifted requires both halves, and every gate now uses it, which also
settles the two different predicates that were in use for the same question.
quickLiftLoadChains returns an empty list for a NULL file as well, so the older
bed and genePred callers are covered whatever their gate does.

quickLiftSql now checks that a row has at least as many columns as the loader is
going to read.  The native psl loader has always checked this, and the quickLift
path replacing it did not, so a table of the wrong type walked off the end of the
row; the psl caller now states the 21 columns it needs.

quickLiftMafs held a maf component name in a fixed buffer through safecpy, which
aborts rather than truncates, so a long name from a hub took hgTracks down.  It
clones instead.

htcBigPslAliInWindow used a trackDb pointer its lookup can leave NULL, which its
sibling htcBigPslAli already checked for.  And aliTrackParam formats a URL
parameter into a fixed buffer with safef, which aborts on a long one.

refs #38249

diff --git src/hg/hgTracks/wigMafTrack.c src/hg/hgTracks/wigMafTrack.c
index 1bcec853473..bbad7678310 100644
--- src/hg/hgTracks/wigMafTrack.c
+++ src/hg/hgTracks/wigMafTrack.c
@@ -328,31 +328,31 @@
 
 static void loadMafsToTrack(struct track *track)
 /* load mafs in region to track custom pointer */
 {
 struct sqlConnection *conn;
 struct sqlConnection *conn2;
 struct mafPriv *mp = getMafPriv(track);
 
 if (inSummaryMode(cart, track->tdb, winBaseCount))
     return;
 
 int begin = winStart - 2;
 if (begin < 0)
     begin = 0;
 
-if (trackDbSetting(track->tdb, "quickLiftDb") != NULL)
+if (quickLiftIsLifted(track->tdb))
     mp->list = quickLiftLoadMafs(track, begin, winEnd + 2);
 else if (track->isBigBed)
     {
     struct bbiFile *bbi = fetchBbiForTrack(track);
     mp->list = bigMafLoadInRegion(bbi, chromName, begin, winEnd+2);
     bbiFileClose(&bbi);
     track->bbiFile = NULL;
     }
 else if (mp->ct)
     {
 /* we open two connections to the database
  * that has the maf track in it.  One is
  * for the scoredRefs, the other to access
  * the extFile database.  We could get away
  * with just one connection, but then we'd
@@ -548,31 +548,31 @@
 struct track *wigTrack = track->subtracks;
 int scoreHeight = tl.fontHeight * 4;
 char *snpTable = trackDbSetting(track->tdb, "snpTable");
 boolean doSnpTable = FALSE;
 if ( (track->limitedVis == tvPack) && (snpTable != NULL) && 
     cartOrTdbBoolean(cart, track->tdb, MAF_SHOW_SNP,FALSE))
     doSnpTable = TRUE;
 
 // the maf's only get loaded if we're not in summary or snpTable views
 if (!doSnpTable && !inSummaryMode(cart, track->tdb, winBaseCount))
     {
     /* "close in" display uses actual alignments from file */
     struct mafPriv *mp = getMafPriv(track);
     struct sqlConnection *conn, *conn2;
 
-    if (trackDbSetting(track->tdb, "quickLiftDb") != NULL)
+    if (quickLiftIsLifted(track->tdb))
         mp->list = quickLiftLoadMafs(track, winStart, winEnd);
     else if (track->isBigBed)
         {
         struct bbiFile *bbi = fetchBbiForTrack(track);
         mp->list = bigMafLoadInRegion(fetchBbiForTrack(track), chromName, winStart, winEnd);
         bbiFileClose(&bbi);
         track->bbiFile = NULL;
         }
     else if (mp->ct)
 	{
 	char *fileName = getCustomMafFile(track);
 	conn = hAllocConn(CUSTOM_TRASH);
 	conn2 = hAllocConn(CUSTOM_TRASH);
 	mp->list = wigMafLoadInRegion(conn, conn2, mp->ct->dbTableName,
 					chromName, winStart, winEnd, fileName);