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/hgc/hgc.c src/hg/hgc/hgc.c index 092fd629965..4c8c4965512 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -3835,31 +3835,31 @@ struct chain *lifted = quickLiftChain(chainHash, &mapPsls, chain); if (lifted != NULL) return lifted; } } return NULL; } struct chain *chainLoadItemInRange(struct trackDb *tdb, char *item) /* Load up parts of chain that intersect seqName:winStart-winEnd */ { struct chain *chain = NULL; int id = sqlUnsigned(item); -if ((trackDbSetting(tdb, "quickLiftDb") != NULL) && !quickLiftIsOwnChainTrack(tdb)) +if (quickLiftIsLifted(tdb) && !quickLiftIsOwnChainTrack(tdb)) { chain = quickLiftChainInRange(tdb, id); if (chain == NULL) errAbort("Couldn't lift chain %d into %s:%d-%d", id, seqName, winStart, winEnd); return chain; } if (startsWith("big", tdb->type)) { char *fileName = trackDbSetting(tdb, "bigDataUrl"); char *linkFileName = trackDbSetting(tdb, "linkDataUrl"); if (linkFileName == NULL) { char *bigDataUrl = cloneString(trackDbSetting(tdb, "bigDataUrl")); char *dot = strrchr(bigDataUrl, '.'); @@ -4173,31 +4173,31 @@ struct sqlResult *sr; char **row; sqlSafef(query, ArraySize(query), "select normScore from %s where id = '%s'", tableName, item); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { double normScore = atof(row[0]); int basesAligned = chain->score / normScore; printf("Normalized Score: %1.0f (aligned bases: %d)", normScore, basesAligned); } sqlFreeResult(&sr); printf("
\n"); } -if ((trackDbSetting(tdb, "quickLiftDb") != NULL) && !quickLiftIsOwnChainTrack(tdb)) +if (quickLiftIsLifted(tdb) && !quickLiftIsOwnChainTrack(tdb)) // A lifted chain is only worked out over the window being viewed, so the whole chain's // extent is not knowable here and the usual sentence would be wrong. printf("
This chain comes from %s and is mapped onto %s as the browser draws it, so " "the fields above describe the part of it around the window rather than the " "whole chain.
\n", trackDbSetting(tdb, "quickLiftDb"), trackHubSkipHubName(database)); else printf("
Fields above refer to entire chain or gap, not just the part inside the window.
\n"); printf("
\n"); chainWinSize = min(winEnd-winStart, chain->tEnd - chain->tStart); /* Show alignment if the database exists and */ /* if there is a chromInfo table for that database and the sequence */ /* file exists. This means that alignments can be shown on the archive */ /* server (or in other cases) if there is a database with a chromInfo table, */ @@ -7064,31 +7064,31 @@ } gbWarnFree(&gbWarn); sqlFreeResult(&sr); dyStringFree(&dy); hFreeConn(&conn); hFreeConn(&conn2); } static char *aliTrackParam() /* "&aliTrack=" for the track hgc was called on, so an alignment handler can find * its trackDb. The aliTable name alone will not do: a quickLifted track's table name is * the one from the assembly the alignments came from, and that name usually also belongs * to a real table on the assembly being viewed. */ { -static char buf[256]; +static char buf[1024]; safef(buf, sizeof buf, "&aliTrack=%s", cgiUsualString("table", cgiUsualString("g", ""))); return buf; } static boolean isPslToPrintByClick(struct psl *psl, int startFirst, boolean isClicked) /* Determine if a psl should be printed based on if it was or was not the one that was clicked * on. */ { return ((psl->tStart == startFirst) && sameString(psl->tName, seqName)) == isClicked; } void printAlignmentsSimple(struct psl *pslList, int startFirst, char *hgcCommand, char *tableName, char *itemIn) @@ -8813,30 +8813,32 @@ } void htcBigPslAliInWindow(char *acc) /* Show alignment in window for accession in bigPsl file. */ { struct psl *partPsl, *wholePsl; char *aliTable; int start; unsigned int cdsStart = 0, cdsEnd = 0; struct trackDb *tdb = NULL; aliTable = cartString(cart, "aliTable"); struct quickLiftAli ali; quickLiftAliInfo(aliTable, &ali); tdb = ali.tdb; +if (tdb == NULL) + errAbort("BUG: bigPsl alignment table '%s' not found; this maybe causes by `.' in track names", aliTable); char title[1024]; safef(title, sizeof title, "%s vs Genomic [%s]", acc, aliTable); htmlFramesetStart(title); /* Get some environment vars. */ start = cartInt(cart, "l"); int end = cartInt(cart, "r"); char *chrom = cartString(cart, "c"); char *seq = NULL, *cdsString = NULL; struct lm *lm = lmInit(0); char *fileName = bbiNameFromSettingOrTable(tdb, NULL, tdb->table); struct bbiFile *bbi = bigBedFileOpenAlias(fileName, chromAliasFindAliases); unsigned seqTypeField = bbExtraFieldIndex(bbi, "seqType"); struct hash *chainHash = NULL, *mapPsls = NULL;