90dc829b2d87b15c4fc4bbc1d814f83d1274ef52
braney
  Fri Sep 4 14:00:05 2026 -0700
Pass element counts, not byte sizes, to the chop routines

chopByWhite, chopString and chopByChar take their last argument as a
count of elements in the output array.  Fifteen call sites passed
sizeof(array) instead.  For an array of pointers that is eight times
the real capacity on a 64-bit build, so the chop could write well past
the end of the array.

Switched each to ArraySize().  Behaviour is unchanged for any input
that already fitted in the array.

Built clean: lib, hg/lib, hg/hgTracks, hg/hgc, hg/utils/hubCheck,
utils/bedScore, parasol/lib, parasol/parasol.  Three directories do not
build, but they fail the same way without this change: checkExp is
missing htslib link flags, and cgapSageFind and affySplice have stale
prototypes in files this does not touch.

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

diff --git src/hg/makeDb/trackDbRaFormat/trackDbRaFormat.c src/hg/makeDb/trackDbRaFormat/trackDbRaFormat.c
index 4266bfefa65..5b845ce5f1c 100644
--- src/hg/makeDb/trackDbRaFormat/trackDbRaFormat.c
+++ src/hg/makeDb/trackDbRaFormat/trackDbRaFormat.c
@@ -1,139 +1,139 @@
 /* trackDbRaFormat - read trackDb.ra file and format with standard whitespace */
 
 /* Copyright (C) 2011 The Regents of the University of California 
  * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 #include "common.h"
 #include "linefile.h"
 #include "options.h"
 #include "ra.h"
 #include "hash.h"
 
 
 void usage()
 /* Explain usage and exit. */
 {
 errAbort(
   "trackDbRaFormat - Format trackDb.ra canonically.\n\n"
   "usage:\n"
   "   trackDbRaFormat in.ra out.ra\n"
   );
 }
 
 /* for checking label lengths */
 #define MAX_SHORT_LABEL 17
 #define MAX_LONG_LABEL 80
 
 static struct optionSpec options[] = {
    {NULL, 0},
 };
 
 void trackDbRaFormat(char *inFile, char *outFile)
 /* Output ra stanzas as lines */
 {
 struct lineFile *lf = lineFileOpen(inFile, TRUE);
 FILE *of = mustOpen(outFile, "w");
 char *line, *start;
 int indent = 0;
 char *words[1024];
 int ct;
 char *trackName;
 struct hash *ra;
 struct hash *raHash = hashNew(0);
 char *setting;
 boolean stanza = FALSE;
 int i;
 char *label;
 int len;
 
 /* load all track stanzas into hash so we can lookup type while
  * processing line by line */
 
 while ((ra = raNextRecord(lf)) != NULL)
     {
     trackName = hashFindVal(ra, "track");
     if (trackName != NULL)
         hashAdd(raHash, trackName, ra);
     }
 
 lineFileSeek(lf, 0, SEEK_SET);
 
 /* read and format line by line */
 
 while (lineFileNext(lf, &line, NULL))
     {
     start = skipLeadingSpaces(line);
     if (*start == 0)
         {
         /* empty line */
         fputc('\n', of);
         stanza = FALSE;
         }
     else if (startsWith("#", start))
         {
         /* comment */
         fputs(line, of);
         fputc('\n', of);
         }
     else if (!stanza)
         {
         /* first line in ra stanza -- test for track line */
         if (differentString(nextWord(&line), "track"))
             continue;
         stanza = TRUE;
         trackName = nextWord(&line);
         ra = (struct hash *)hashMustFindVal(raHash, trackName);
 
         /* determine  indent based on track type */
         indent = 0;
         if (hashFindVal(ra, "subTrack"))
             indent = 4;
         else 
             {
             setting = hashFindVal(ra, "superTrack");
             if (setting && sameString(setting, "on"))
                 indent = 8;
             }
         spaceOut(of, indent);
         fprintf(of, "track %s\n", trackName);
 
         /* check label lengths */
         label = hashFindVal(ra, "shortLabel");
         if (label)
             if ((len = strlen(label)) > MAX_SHORT_LABEL)
                 verbose(1, "Short label '%s' too long (%d chars) for track '%s'\n", 
                                 label, len-MAX_SHORT_LABEL, trackName);
         label = hashFindVal(ra, "longLabel");
         if (label)
             if ((len = strlen(label)) > MAX_LONG_LABEL)
                 verbose(1, "Long label '%s' too long (%d chars) for track '%s'\n", 
                                 label, len - MAX_LONG_LABEL, trackName);
         }
     else 
         {
         /* subsequent lines in ra stanza */
         /* indent properly, squeeze out extra whitespace within settings */
         spaceOut(of, indent);
-        ct = chopByWhite(line, words, sizeof(words));
+        ct = chopByWhite(line, words, ArraySize(words));
         for (i = 0; i < ct; i++)
             {
             fputs(words[i], of);
             if (i < ct-1)
                 fputc(' ', of);
             else
                 fputc('\n', of);
             }
         }
     }
 fflush(of);
 fclose(of);
 }
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 optionInit(&argc, argv, options);
 if (argc != 3)
     usage();
 trackDbRaFormat(argv[1], argv[2]);
 return 0;
 }