f57fc11d951807e19b20b5960e735fa50eaea279
braney
  Fri Jun 12 13:10:00 2026 -0700
Fix more warnings exposed by -O3 build across hg utils and errAbort

Continuation of the -O3 cleanup: a full clean rebuild surfaced warnings in
many programs whose objects had not been recompiled before.  Most are the same
mechanical patterns as the first batch (strncpy -> safecpy/memcpy, sprintf ->
safef), plus a few that needed more thought:

- errAbort.h: mark errAbort/vaErrAbort/errnoAbort/noWarnAbort as noreturn.
They provably never return (longjmp or exit; the existing "to make compiler
happy" exit(-1) in noWarnAbort confirms the intent), and this lets GCC prune
the impossible null paths after an errAbort guard, fixing false-positive
null-deref / overread warnings in mafAddIRows, mafAddIRowsStream and
phyloPlace with no source change to those files.
- altSplice.c (hgGene): real one-element stack buffer overflow.  makeGrayShades
writes shadesOfGray[maxShade+1], but the caller declared shadesOfGray[9] with
maxShade=8.  Grow the array to [10] (maxShade stays 8); behavior unchanged.
- hgc.c bedPrintPos: ~60 callers pass a track-specific struct cast to
(struct bed *) and read only its bed-compatible leading fields.  At -O3
-Warray-bounds flags the casts because the real object is smaller than
struct bed; the reads are safe by the bed-layout convention, so suppress
-Warray-bounds around just that function.
- mafsInRegion.c: chromFromSrc returns strchr(src,'.')+1, which GCC mis-sizes
as a 0-byte region when handed to strcmp via sameString/differentString;
suppress the false-positive -Wstringop-overread around extractMafs.
- sanger22gtf.c, bottleneck.c: put the printf/fprintf in the else of the
NULL guard so -Wformat-overflow (which runs before the noreturn-based
pruning) can see the argument is non-null.

safecpy/memcpy/safef conversions: basicBed already done earlier; here
haplotypes (memcpy of the original pointer pun), gbToFaRa, motifSig,
hgClonePos, featureBits, libScan, hgGoldGapGl, hgSoftPromoter, mafClick,
mafAddQRows, hgc.c, stanToBedAndExpRecs, bedUp, faSplit, trfBig,
splitFaIntoContigs, aladdin, ameme.

A full clean tree now builds with no warnings at -O3.

refs #37761

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

diff --git src/hg/featureBits/featureBits.c src/hg/featureBits/featureBits.c
index 9cf0a12444b..c017e4063c1 100644
--- src/hg/featureBits/featureBits.c
+++ src/hg/featureBits/featureBits.c
@@ -282,46 +282,46 @@
         fprintf(stderr,"Out of order: %d,%d\n", lastStart, start);
     if (rangeIntersection(lastStart, lastEnd, start-1, end) > 0)
         fprintf(stderr,"Overlapping: (%d %d) (%d %d)\n", lastStart, lastEnd, start, end);
     lastStart = start;
     lastEnd = end;
     }
 sqlFreeResult(&sr);
 errAbort("All for now");
 }
 
 char *chromFileName(char *track, char *chrom, char fileName[512])
 /* Return chromosome specific version of file if it exists. */
 {
 if (fileExists(track))
     {
-    strncpy(fileName, track, 512);
+    safecpy(fileName, 512, track);
     }
 else
     {
     char dir[PATH_LEN], root[FILENAME_LEN], ext[FILEEXT_LEN];
     int len;
     splitPath(track, dir, root, ext);
     /* Chop trailing / off of dir. */
     len = strlen(dir);
     if (len > 0 && dir[len-1] == '/')
         dir[len-1] = 0;
     safef(fileName, 512, "%s/%s%s%s", dir, chrom, root, ext);
     if (!fileExists(fileName))
 	{
         warn("Couldn't find %s or %s", track, fileName);
-	strncpy(fileName, track, 512);
+	safecpy(fileName, 512, track);
 	}
     }
 return fileName;
 }
 
 void outOfRange(struct lineFile *lf, char *chrom, int chromSize)
 /* Complain that coordinate is out of range. */
 {
 errAbort("Coordinate out of allowed range [%d,%d) for %s near line %d of %s",
 	0, chromSize, chrom, lf->lineIx, lf->fileName);
 }
 
 void setPslBits(struct lineFile *lf, 
 	Bits *bits, struct psl *psl, int winStart, int winEnd)
 /* Set bits that are in psl. */
@@ -494,31 +494,31 @@
             if (s < 0) outOfRange(lf, chrom, chromSize);
             if (e > chromSize) outOfRange(lf, chrom, chromSize);
             bitSetRange(acc, b->tStart, b->tEnd - b->tStart);
             }
         }
     chainFree(&chain);
     }
 lineFileClose(&lf);
 }
 
 
 void isolateTrackPartOfSpec(char *spec, char track[512])
 /* Convert something like track:exon to just track */
 {
 char *s;
-strncpy(track, spec, 512);
+safecpy(track, 512, spec);
 s = strchr(track, ':');
 if (s != NULL) *s = 0;
 }
 
 void orFile(Bits *acc, char *track, char *chrom, int chromSize)
 /* Or some sort of file into bits. */
 {
 if (isFileType(track, "psl"))
     {
     fbOrPsl(acc, track, chrom, chromSize);
     }
 else if (isFileType(track, "bed"))
     {
     fbOrBed(acc, track, chrom, chromSize);
     }