099dda2013e7caffde097371fa68de467a2c5085 max Tue Jun 30 05:14:13 2026 -0700 hgBlat: fix bugs in showAliPlaces BLAT results page - Fix inverted JS test in buildBigPslCt: 'if (!ct_blat !== "")' always evaluated true (a boolean strict-compared to a string), so the remove-custom-track vars were appended on every call. Should be 'if (ct_blat !== "")'. - Escape trackName/trackDescription with javaScriptLiteralEncode before interpolating them into single-quoted JS literals. They derive from the user FASTA header (psl->qName), so a quote broke the script / allowed injection. - Remove a stray re-opened <TT><PRE> in the PSL-output branch that left unbalanced tags. - Free the leaked locusConn connection and subList in the hyperlink branch. diff --git src/hg/hgBlat/hgBlat.c src/hg/hgBlat/hgBlat.c index 2c58ecc9795..bbed0916c9e 100644 --- src/hg/hgBlat/hgBlat.c +++ src/hg/hgBlat/hgBlat.c @@ -539,31 +539,30 @@ cartWebEnd(); } } else if (pslOut) { if (!pslRawOut) printf("<TT><PRE>"); if (!sameString(output, "psl no header")) pslxWriteHead(stdout, qType, tType); for (psl = pslList; psl != NULL; psl = psl->next) pslTabOut(psl, stdout); if (pslRawOut) exit(0); - printf("<TT><PRE>"); printf("</PRE></TT>"); } else if (jsonOut) { webStartText(); pslWriteAllJson(pslList, stdout, database, TRUE); exit(0); } else // hyperlink { printf("<H2>BLAT Search Results</H2>"); char* posStr = cartOptionalString(cart, "position"); if (posStr != NULL) printf("<P>Go back to <A HREF=\"%s\">%s</A> on the Genome Browser.</P>\n", browserUrl, posStr); @@ -636,58 +635,60 @@ } if (!feelingLucky) { // REMOVE CT BUTTON FORM. printf("<div id=deleteCtForm style='display: none'>\n"); printf("<FORM ACTION=\"%s?hgsid=%s&db=%s\" NAME=\"MAIN_FORM\" METHOD=%s>\n\n", hgTracksName(), cartSessionId(cart), database, cartUsualString(cart, "formMethod", "POST")); cartSaveSession(cart); cgiMakeButton(CT_DO_REMOVE_VAR, "Delete Custom Track"); cgiMakeHiddenVar(CT_SELECTED_TABLE_VAR, "FAKETRACKNAME"); printf("</FORM>\n"); printf("</div>\n"); } + char *trackNameJs = javaScriptLiteralEncode(trackName); + char *trackDescriptionJs = javaScriptLiteralEncode(trackDescription); jsInlineF( "var ct_blat = '';\n" "\n" "function buildBigPslCtSuccess (content, status)\n" "{ // Finishes the successful creation of blat ct bigPsl. Called by ajax return.\n" " // saves the ct name so it can be used later for rename or delete.\n" "\n" "var matchWord = '&table=';\n" "var ct_blatPos = content.indexOf(matchWord) + matchWord.length;\n" "\n" "if (ct_blatPos >= 0)\n" " {\n" " var ct_blatPosEnd = content.indexOf('\"', ct_blatPos);\n" " ct_blat = content.slice(ct_blatPos, ct_blatPosEnd);\n" " if (luckyLocation == '')\n" " {\n" " $('input[name=\""CT_SELECTED_TABLE_VAR"\"]')[0].value = ct_blat;\n" " $('input[name=\""CT_SELECTED_TABLE_VAR"\"]')[1].value = ct_blat;\n" " }\n" " }\n" "}\n" "\n" "function buildBigPslCt (url, trackName, trackDescription)\n" "{ // call hgc to buildBigPsl from blat result.\n" "\n" "var cgiVars = 'trackName='+encodeURIComponent(trackName)+'&trackDescription='+encodeURIComponent(trackDescription);\n" - "if (!ct_blat !== '')\n" + "if (ct_blat !== '')\n" " {\n" " cgiVars += '&"CT_DO_REMOVE_VAR"='+encodeURIComponent('Remove Custom Track');\n" " cgiVars += '&"CT_SELECTED_TABLE_VAR"='+encodeURIComponent(ct_blat);\n" " }\n" "\n" "$.ajax({\n" " type: 'GET',\n" " url: url,\n" " data: cgiVars,\n" " dataType: 'html',\n" " trueSuccess: buildBigPslCtSuccess,\n" " success: catchErrorOrDispatch,\n" " error: errorHandler,\n" " cache: false,\n" " async: false\n" @@ -697,31 +698,33 @@ "var url='%s';\n" "var trackName='%s';\n" "var trackDescription='%s';\n" "$(document).ready(function() {\n" "\n" "buildBigPslCt(url, trackName, trackDescription);\n" "if (luckyLocation !== '')\n" " {\n" " location.replace(luckyLocation);\n" " }\n" "else\n" " {\n" " $('#renameFormItem')[0].style.display = 'block';\n" " $('#deleteCtForm')[0].style.display = 'block';\n" " }\n" - "});\n", url->string, trackName, trackDescription); + "});\n", url->string, trackNameJs, trackDescriptionJs); + freeMem(trackNameJs); + freeMem(trackDescriptionJs); // RENAME CT JS CODE if (!feelingLucky) jsInline("$('#showRenameForm').click(function(){\n" " $('#renameForm')[0].style.display = 'block';\n" " $('#renameFormItem')[0].style.display = 'none';\n" " $('#showRenameForm')[0].style.display = 'none';\n" " $('input[name=\"trackName\"]')[0].value = trackName;\n" " $('input[name=\"trackDescription\"]')[0].value = trackDescription;\n" "return false;\n" "});\n"); // RENAME CT JS CODE if (!feelingLucky) @@ -904,30 +907,33 @@ psl->tEnd - psl->tStart); // if you modify this, also modify hgPcr.c:doQuery, which implements a similar feature char *seq = psl->tName; if (endsWith(seq, "_fix")) printf(" <A target=_blank HREF=\"../FAQ/FAQdownloads.html#downloadFix\">What is chrom_fix?</A>"); else if (endsWith(seq, "_alt")) printf(" <A target=_blank HREF=\"../FAQ/FAQdownloads.html#downloadAlt\">What is chrom_alt?</A>"); else if (endsWith(seq, "_random")) printf(" <A target=_blank HREF=\"../FAQ/FAQdownloads.html#download10\">What is chrom_random?</A>"); else if (startsWith(seq, "chrUn")) printf(" <A target=_blank HREF=\"../FAQ/FAQdownloads.html#download11\">What is a chrUn sequence?</A>"); printf("\n"); } printf("</PRE>\n"); + if (locusConn != NULL) + hFreeConn(&locusConn); + subTextFreeList(&subList); webNewSection("Help"); puts("<P style=\"text-align:left\"><A target=_blank HREF=\"../FAQ/FAQblat.html#blat1b\">Missing a match?</A><br>"); puts("<A target=_blank HREF=\"../FAQ/FAQblat.html#blat1c\">What is chr_alt & chr_fix?</A></P>\n"); puts("</DIV>\n"); } pslFreeList(&pslList); } void trimUniq(bioSeq *seqList) /* Check that all seq's in list have a unique name. Try and * abbreviate longer sequence names. */ { struct hash *hash = newHash(0); bioSeq *seq;