fb50a1cca3a117bb964c43196671142484b13bf9
braney
  Fri Jun 12 12:10:47 2026 -0700
lib jkOwnLib hg/lib: fix warnings exposed by -O3 build

At -O3 GCC does more inlining and interprocedural range analysis, which
surfaces several warnings that -O -g never triggered.  With -Werror these
break the build, so fix them ahead of switching the default to -O3.

- bamFile.c: move setenv() into the else of its NULL guard so it is not
reachable with a NULL argument (-Wnonnull, seen via inlining of bamFetch).
- basicBed.c, wormdna.c, bedDetail.c, customFactory.c, hdb.c, qaSeq.c:
replace strncpy() with safecpy() where the result must be terminated
(-Wstringop-truncation).
- htmshell.c: use memcpy() for the intentional exact-length, non-terminated
copy (-Wstringop-truncation).
- obscure.c: compute the comma groups in sprintLongWithCommas() with % 1000
so the compiler can see each %03lld argument is bounded (-Wformat-overflow).
- crudeali.c: do the endian type-pun through a union so strict-aliasing
analysis no longer reports the value as uninitialized (-Wuninitialized).
- jksql.c: wrap a possibly-NULL database name in naForNull() before passing
it to %s (-Wformat-overflow).

refs #37761

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

diff --git src/hg/lib/bedDetail.c src/hg/lib/bedDetail.c
index 85f16161790..99dc0b2cd58 100644
--- src/hg/lib/bedDetail.c
+++ src/hg/lib/bedDetail.c
@@ -325,31 +325,31 @@
 AllocVar(item);
 item->chrom = cloneString(row[0]);
 item->chromStart = lineFileNeedNum(lf, row, 1);
 item->chromEnd = lineFileNeedNum(lf, row, 2);
 if (item->chromEnd < 1)
     lineFileAbort(lf, "chromEnd less than 1 (%d)", item->chromEnd);
 if (item->chromEnd < item->chromStart)
     lineFileAbort(lf, "chromStart after chromEnd (%d > %d)",
         item->chromStart, item->chromEnd);
 if (wordCount > 3)
      item->name = cloneString(row[3]);
 if (wordCount > 4)
      item->score = lineFileNeedNum(lf, row, 4);
 if (wordCount > 5)
      {
-     strncpy(item->strand, row[5], sizeof(item->strand));
+     safecpy(item->strand, sizeof(item->strand), row[5]);
      if (item->strand[0] != '+' && item->strand[0] != '-' && item->strand[0] != '.')
           lineFileAbort(lf, "Expecting + or - in strand");
      }
 if (wordCount > 6)
      item->thickStart = lineFileNeedNum(lf, row, 6);
 else
      item->thickStart = item->chromStart;
 if (wordCount > 7)
      {
      item->thickEnd = lineFileNeedNum(lf, row, 7);
      if (item->thickEnd < item->thickStart)
          lineFileAbort(lf, "thickStart after thickEnd");
      if ((item->thickStart != 0) &&
          ((item->thickStart < item->chromStart) ||
           (item->thickStart > item->chromEnd)))