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/pslTrack.c src/hg/hgTracks/pslTrack.c index d1b79ccc173..b7380a339e6 100644 --- src/hg/hgTracks/pslTrack.c +++ src/hg/hgTracks/pslTrack.c @@ -412,53 +412,53 @@ static void quickLiftLfFromPsls(struct track *tg, char *chrom, int start, int end, boolean isXeno, boolean nameGetsPos) /* Read alignments out of the assembly the track was lifted from, map them onto the * reference, and turn them into linked features. */ { char *liftDb = trackDbSetting(tg->tdb, "quickLiftDb"); char *table = NULL; quickLiftResolveTable(tg->tdb, tg->table, &table, &liftDb); char *quickLiftFile = trackDbSetting(tg->tdb, "quickLiftUrl"); char extraWhere[128]; struct hash *chainHash = newHash(8); struct sqlConnection *conn = hAllocConn(liftDb); struct psl *pslList = (struct psl *)quickLiftSql(conn, quickLiftFile, table, chrom, start, end, NULL, pslChromFilterWhere(tg, extraWhere, sizeof(extraWhere)), - pslRowLoader, 0, chainHash); + pslRowLoader, 21, chainHash); hFreeConn(&conn); struct linkedFeatures *lfList = NULL; struct psl *psl, *nextPsl; for(psl = quickLiftPsls(chainHash, pslList); psl != NULL; psl = nextPsl) { nextPsl = psl->next; psl->next = NULL; // lfFromPslx hangs on to the psl, so don't leave it in a list // sizeMul is 1 whatever the caller passed: the lift returns an untranslated // alignment, and it puts a protein alignment into nucleotide space on the way, so the // block sizes are already in bases. slAddHead(&lfList, lfFromPslx(psl, 1, isXeno, nameGetsPos, tg)); } finishPslLfList(tg, lfList); } static void lfFromPslsInRange(struct track *tg, int start, int end, char *chrom, boolean isXeno, boolean nameGetsPos, int sizeMul) /* Return linked features from range of table. */ { -if (trackDbSetting(tg->tdb, "quickLiftDb") != NULL) +if (quickLiftIsLifted(tg->tdb)) { quickLiftLfFromPsls(tg, chrom, start, end, isXeno, nameGetsPos); return; } struct sqlConnection *conn = hAllocConn(database); connectedLfFromPslsInRange(conn, tg, start, end, chrom, isXeno, nameGetsPos, sizeMul); hFreeConn(&conn); } static void loadXenoPslWithPos(struct track *tg) /* load up all of the psls from correct table into tg->items item list*/ { lfFromPslsInRange(tg, winStart,winEnd, chromName, TRUE, TRUE, 1);