e6b0dc7877ae4b24f56682885e03263fd2da3582
braney
  Tue Aug 18 11:37:04 2026 -0700
lib, hgc: encode barChart, BAM and VCF detail text consistently, refs #38123

diff --git src/hg/hgc/bamClick.c src/hg/hgc/bamClick.c
index 76e73c81998..7d18f661886 100644
--- src/hg/hgc/bamClick.c
+++ src/hg/hgc/bamClick.c
@@ -1,27 +1,28 @@
 /* bamClick - handler for alignments in BAM format (produced by MAQ,
  * BWA and some other short-read alignment tools). */
 
 /* Copyright (C) 2014 The Regents of the University of California 
  * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 
 #include "common.h"
 #include "hash.h"
 #include "hdb.h"
 #include "hgBam.h"
 #include "hgc.h"
 #include "hui.h"
+#include "htmshell.h"
 #include "knetUdc.h"
 #include "udc.h"
 #include "chromAlias.h"
 
 
 #include "hgBam.h"
 #include "hgConfig.h"
 
 struct bamTrackData
     {
     int itemStart;
     char *itemName;
     struct hash *pairHash;
     boolean foundIt;
     };
@@ -120,31 +121,32 @@
 puts("<BR>");
 if (bamIsRc(bam))
     printf("<em>Note: although the read was mapped to the reverse strand of the genome, "
 	   "the sequence and CIGAR in BAM are relative to the forward strand.</em><BR>\n");
 puts("<BR>");
 struct dnaSeq *genoSeq = hChromSeq(database, seqName, tStart, tEnd);
 char *qSeq = bamGetQuerySequence(bam, FALSE);
 if (core->l_qseq > 5000)
     printf("<B>Alignment not shown, query sequence is %d bp long &gt; 5000bp</B><BR>\n", core->l_qseq);
 else
     {
     if (isNotEmpty(qSeq) && !sameString(qSeq, "*"))
         {
         char *qSeq = NULL;
         struct ffAli *ffa = bamToFfAli(bam, genoSeq, tStart, useStrand, &qSeq);
-        printf("<B>Alignment of %s to %s:%d-%d%s:</B><BR>\n", itemName,
+        // the read name comes straight out of the BAM file, so encode it before output
+        printf("<B>Alignment of %s to %s:%d-%d%s:</B><BR>\n", htmlEncode(itemName),
                seqName, tStart+1, tEnd, (isRc ? " (reverse complemented)" : ""));
         ffShowSideBySide(stdout, ffa, qSeq, 0, genoSeq->dna, tStart, tLength, 0, tLength, 8, isRc,
                          FALSE);
         }
     }
 
 if (!skipQualityScore && core->l_qseq > 0)
     {
     if (core->l_qseq > 5000)
         {
         printf("<B>Sequence quality not shown, query sequence %d bp long &gt; 5000bp</B><BR>\n", core->l_qseq);
         } 
     else
         {
         printf("<B>Sequence quality scores:</B><BR>\n<TT><TABLE><TR>\n");
@@ -192,57 +194,57 @@
     puts(rightSeq);
     puts("</TT></PRE>");
     }
 }
 
 static void bamPairDetails(const bam1_t *leftBam, const bam1_t *rightBam)
 /* Print out details for paired-end reads. */
 {
 if (leftBam && rightBam)
     {
     const bam1_core_t *leftCore = &leftBam->core, *rightCore = &rightBam->core;
     int leftLength = bamGetTargetLength(leftBam), rightLength = bamGetTargetLength(rightBam);
     int start = min(leftCore->pos, rightCore->pos);
     int end = max(leftCore->pos+leftLength, rightCore->pos+rightLength);
     char *itemName = bam1_qname(leftBam);
-    printf("<B>Paired read name:</B> %s<BR>\n", itemName);
+    printf("<B>Paired read name:</B> %s<BR>\n", htmlEncode(itemName));
     printPosOnChrom(seqName, start, end, NULL, FALSE, itemName);
     puts("<P>");
     }
 showOverlap(leftBam, rightBam);
 printf("<TABLE><TR><TD valign=top><H4>Left end read</H4>\n");
 singleBamDetails(leftBam);
 printf("</TD><TD valign=top><H4>Right end read</H4>\n");
 singleBamDetails(rightBam);
 printf("</TD></TR></TABLE>\n");
 }
 
 static int oneBam(const bam1_t *bam, void *data, bam_hdr_t *header)
 /* This is called on each record retrieved from a .bam file. */
 {
 const bam1_core_t *core = &bam->core;
 if (core->flag & BAM_FUNMAP)
     return 0;
 struct bamTrackData *btd = (struct bamTrackData *)data;
 if (sameString(bam1_qname(bam), btd->itemName))
     {
     btd->foundIt = TRUE;
     if (btd->pairHash == NULL || (core->flag & BAM_FPAIRED) == 0)
 	{
 	if (core->pos == btd->itemStart)
 	    {
-	    printf("<B>Read name:</B> %s<BR>\n", btd->itemName);
+	    printf("<B>Read name:</B> %s<BR>\n", htmlEncode(btd->itemName));
 	    singleBamDetails(bam);
 	    }
 	}
     else
 	{
 	bam1_t *firstBam = (bam1_t *)hashFindVal(btd->pairHash, btd->itemName);
 	if (firstBam == NULL)
 	    hashAdd(btd->pairHash, btd->itemName, bamClone(bam));
 	else
 	    {
 	    bamPairDetails(firstBam, bam);
 	    hashRemove(btd->pairHash, btd->itemName);
 	    }
 	}
     }