e2d86e5b1db3e603f503f58db38009fa31840dd5 braney Wed Sep 9 12:37:09 2026 -0700 hgTracks: don't read past the end of exonFrames on a transcript's last exon The exon mouseover works out the codon phase at each end of an exon. The end phase is the frame of the next exon along the transcript. On the last exon of a forward-strand transcript there is no next exon, and the index has reached the number of exons, so the read was one element past the end of the array. The reverse-strand branch already guarded the same case at its own end of the transcript. Nothing the reader sees changes. makeExonFrameText prints an end phase only when the exon is not the last one, so the value read here was always thrown away. Measured on two builds from this tree, patched and not: 591 codon-phase tooltips at chr12:459,900-462,400 are byte for byte the same, while valgrind reports the invalid read in the unpatched build and none in this one. refs #38309 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c index 8babeeef356..3ee4d114db6 100644 --- src/hg/hgTracks/simpleTracks.c +++ src/hg/hgTracks/simpleTracks.c @@ -3162,31 +3162,35 @@ existingText = lf->name; // construct a string that tells the user about the codon frame situation of this exon // char *frameText = ""; // for coding exons, determine the start and end phase of the exon and an English text describing both: // if transcript is on + strand, the start phase is the exonFrame value, and the end phase is the next exonFrame (3' on DNA) value // if transcript is on - strand, the start phase is the previous (=3' on DNA) exonFrame and the end phase is the exonFrame int startPhase = -1; int endPhase = -1; char phaseText[EXONTEXTLEN]; phaseText[0] = 0; if ((gp != NULL) && gp->exonFrames && isExon) { startPhase = gp->exonFrames[exonIx-1]; if (!revStrand) + { + // the last exon has no next exon, so it has no end phase + if (exonIx < gp->exonCount) endPhase = gp->exonFrames[exonIx]; + } else if (exonIx>1) endPhase = gp->exonFrames[exonIx-2]; // construct a string that tells the user about the codon frame situation of this exon makeExonFrameText(exonIntronNumber, numExons, startPhase, endPhase, phaseText); } if (w > 0) // draw exon or intron if width is greater than 0 { // draw mapBoxes for the codons if we are zoomed in far enough if (isExon && lf->codons && zoomedToCdsColorLevel) { struct simpleFeature *codon; struct dyString *codonDy = dyStringNew(0); int codonS, codonE;