72282e5a10d847e7b8fc013b53bcff15e90499e8 max Sat Sep 26 18:27:01 2026 -0700 pslShow: clip alignment blocks to the sequences supplied, a bigPsl with out-of-range query coords could write past the end of the heap buffers diff --git src/lib/pslShow.c src/lib/pslShow.c index a53a68c0e47..2a46cb469da 100644 --- src/lib/pslShow.c +++ src/lib/pslShow.c @@ -1,27 +1,53 @@ /* pslShow - stuff to help visual psl format alignments. * This file is copyright 2002-2004 Jim Kent, but license is hereby * granted for all use - public, private or commercial. */ #include "common.h" #include "dnaseq.h" #include "htmshell.h" #include "psl.h" #include "cda.h" #include "seqOut.h" +static boolean pslBlockInSeqs(struct psl *psl, int i, int qStart, int qSize, + int tStart, int tSize, int mulFactor, int *retQs, int *retTs, int *retSz) +/* Place block i of psl in the query and target sequences we were handed, clipping it to what + * those sequences actually hold. The loops below index arrays that are only as long as the two + * sequences, so a psl whose coordinates do not belong to the sequence it is being displayed + * against - a bigPsl that stores its query side in bases while its block sizes are in codons, + * or any file a track hub cares to supply - would otherwise read and write past their ends. + * Returns FALSE when nothing of the block lands inside both sequences. */ +{ +int qs = psl->qStarts[i] - qStart; +int ts = psl->tStarts[i] - tStart; +int sz = psl->blockSizes[i]; +if (qs < 0 || qs >= qSize || ts < 0 || ts >= tSize) + return FALSE; +if (sz > qSize - qs) + sz = qSize - qs; +if (sz > (tSize - ts) / mulFactor) + sz = (tSize - ts) / mulFactor; +if (sz <= 0) + return FALSE; +*retQs = qs; +*retTs = ts; +*retSz = sz; +return TRUE; +} + static void pslShowAlignmentStranded(struct psl *psl, boolean isProt, char *qName, bioSeq *qSeq, int qStart, int qEnd, char *tName, bioSeq *tSeq, int tStart, int tEnd, FILE *f) /* Show protein/DNA alignment or translated DNA alignment in HTML format. */ { boolean tIsRc = (psl->strand[1] == '-'); boolean qIsRc = (psl->strand[0] == '-'); int mulFactor = (isProt ? 3 : 1); DNA *dna = NULL; /* Mixed case version of genomic DNA. */ int qSize = qSeq->size; char *qLetters = cloneString(qSeq->dna); int qbafStart, tbafStart; int qcfmStart, tcfmStart; int lineWidth = isProt ? 60 : 50; @@ -69,33 +95,34 @@ fputs("Matching bases are colored blue and capitalized. " "Light blue bases mark the boundaries of gaps in either sequence.\n", f); fprintf(f, "
");
tolowers(qLetters);
/* Display query sequence. */
{
struct cfm *cfm;
char *colorFlags = needMem(qSeq->size);
int i,j;
for (i=0; iblockCount; ++i)
{
- int qs = psl->qStarts[i] - qStart;
- int ts = psl->tStarts[i] - tStart;
- int sz = psl->blockSizes[i]-1;
+ int qs, ts, sz;
+ if (!pslBlockInSeqs(psl, i, qStart, qSize, tStart, tSeq->size, mulFactor, &qs, &ts, &sz))
+ continue;
+ sz -= 1; /* this loop marks the first and last base of the block */
colorFlags[qs] = socBrightBlue;
qLetters[qs] = toupper(qLetters[qs]);
colorFlags[qs+sz] = socBrightBlue;
qLetters[qs+sz] = toupper(qLetters[qs+sz]);
if (isProt)
{
for (j=1; jdna[qs+j];
DNA *codon = &tSeq->dna[ts + 3*j];
AA trans = lookupCodon(codon);
if (trans != 'X' && trans == aa)
{
colorFlags[qs+j] = socBlue;
qLetters[qs+j] = toupper(qLetters[qs+j]);
@@ -125,33 +152,33 @@
/* hgc's htcBlatAlignment reorders these sections by matching the literal ""
* and "" prefixes; keep them intact (or update hgc.c) so the reorder still fires. */
fprintf(f, "%s %s:
\n",
tName, (tIsRc ? "(reverse strand)" : ""));
fprintf(f, "");
/* Display DNA sequence. */
{
struct cfm *cfm;
char *colorFlags = needMem(tSeq->size);
int i,j;
int curBlock = 0;
for (i=0; iblockCount; ++i)
{
- int qs = psl->qStarts[i] - qStart;
- int ts = psl->tStarts[i] - tStart;
- int sz = psl->blockSizes[i];
+ int qs, ts, sz;
+ if (!pslBlockInSeqs(psl, i, qStart, qSize, tStart, tSeq->size, mulFactor, &qs, &ts, &sz))
+ continue;
if (isProt)
{
for (j=0; jdna[qs+j];
int codonStart = ts + 3*j;
DNA *codon = &tSeq->dna[codonStart];
AA trans = lookupCodon(codon);
if (trans != 'X' && trans == aa)
{
colorFlags[codonStart] = socBlue;
colorFlags[codonStart+1] = socBlue;
colorFlags[codonStart+2] = socBlue;
toUpperN(dna+codonStart, 3);
}
@@ -196,66 +223,68 @@
/* Display side by side. */
fprintf(f, " \n");
fprintf(f, "Side by Side Alignment*
\n");
fprintf(f, "");
{
struct baf baf;
int i,j;
bafInit(&baf, qSeq->dna, qbafStart, qIsRc,
tSeq->dna, tbafStart, tIsRc, f, lineWidth, isProt);
if (isProt)
{
for (i=0; iblockCount; ++i)
{
- int qs = psl->qStarts[i] - qStart;
- int ts = psl->tStarts[i] - tStart;
- int sz = psl->blockSizes[i];
+ int qs, ts, sz;
+ if (!pslBlockInSeqs(psl, i, qStart, qSize, tStart, tSeq->size, mulFactor,
+ &qs, &ts, &sz))
+ continue;
bafSetPos(&baf, qs, ts);
bafStartLine(&baf);
for (j=0; jdna[qs+j];
int codonStart = ts + 3*j;
DNA *codon = &tSeq->dna[codonStart];
bafOut(&baf, ' ', codon[0]);
bafOut(&baf, aa, codon[1]);
bafOut(&baf, ' ', codon[2]);
}
bafFlushLine(&baf);
}
fprintf( f,
"*When the translated amino acid in the genomic sequence differs from the \n"
"corresponding amino acid in the protein, the coloring indicates the\n"
"similarity of the two amino acids. Similar amino acids are green, \n"
"dissimilar amino acids are red. The sign of the corresponding entry in\n"
"the BLOSUM 62 matrix is used as the basis of this coloring.\n");
}
else
{
- int lastQe = psl->qStarts[0] - qStart;
- int lastTe = psl->tStarts[0] - tStart;
+ int lastQe = max(0, psl->qStarts[0] - qStart);
+ int lastTe = max(0, psl->tStarts[0] - tStart);
int maxSkip = 8;
bafSetPos(&baf, lastQe, lastTe);
bafStartLine(&baf);
for (i=0; iblockCount; ++i)
{
- int qs = psl->qStarts[i] - qStart;
- int ts = psl->tStarts[i] - tStart;
- int sz = psl->blockSizes[i];
+ int qs, ts, sz;
+ if (!pslBlockInSeqs(psl, i, qStart, qSize, tStart, tSeq->size, mulFactor,
+ &qs, &ts, &sz))
+ continue;
boolean doBreak = TRUE;
int qSkip = qs - lastQe;
int tSkip = ts - lastTe;
if (qSkip >= 0 && qSkip <= maxSkip && tSkip == 0)
{
for (j=0; jdna[lastQe+j], '-');
doBreak = FALSE;
}
else if (tSkip > 0 && tSkip <= maxSkip && qSkip == 0)
{
for (j=0; jdna[lastTe+j]);
doBreak = FALSE;