9c7de0bd83bc6e1876dc0b8b7091127629a07bf0
chmalee
  Thu Mar 5 14:32:25 2026 -0800
Fix array size bounds check for /getData/track endpoint to actually limit to 100 requested tracks

diff --git src/hg/hubApi/getData.c src/hg/hubApi/getData.c
index 896e3b7949b..77ecca7d9cc 100644
--- src/hg/hubApi/getData.c
+++ src/hg/hubApi/getData.c
@@ -468,32 +468,34 @@
 if (NULL == tdb)
     apiErrAbort(err400, err400Msg, "failed to find a track hub definition in genome=%s for endpoint '/getData/track'  given hubUrl='%s'", genome, hubUrl);
 
 struct jsonWrite *jw = apiStartOutput();
 jsonWriteString(jw, "hubUrl", hubUrl);
 jsonWriteString(jw, "genome", genome);
 
 struct jsonWrite *columnTypesJw = NULL;
 if (jsonOutputArrays || debug)
     {
     columnTypesJw = jsonWriteNew();
     jsonWriteObjectStart(columnTypesJw, "columnTypes");
     }
 
 // allow optional comma sep list of tracks
-char *tracks[100];
-int numTracks = chopByChar(trackArg, ',', tracks, sizeof(tracks));
+char *tracks[MAX_NUM_TRACKS + 1];
+int numTracks = chopByChar(trackArg, ',', tracks, MAX_NUM_TRACKS+1);
+if (numTracks > MAX_NUM_TRACKS)
+    apiErrAbort(err400, err400Msg, "too many tracks requested, limit to 100 tracks or less for endpoint '/getData/track");
 int i = 0;
 for (i = 0; i < numTracks; i++)
     {
     char *track = cloneString(tracks[i]);
     struct trackDb *thisTrack = findTrackDb(track, tdb);
     if (NULL == thisTrack)
         apiErrAbort(err400, err400Msg, "failed to find specified track=%s in genome=%s for endpoint '/getData/track'  given hubUrl='%s'", track, genome, hubUrl);
     if (trackHasNoData(thisTrack))
         apiErrAbort(err400, err400Msg, "container track '%s' does not contain data, use the children of this container for data access", track);
     if (! isSupportedType(thisTrack->type))
         apiErrAbort(err415, err415Msg, "track type '%s' for track=%s not supported at this time", thisTrack->type, track);
 
     char *bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl");
     struct bbiFile *bbi = bigFileOpen(thisTrack->type, bigDataUrl);
     if (NULL == bbi)
@@ -607,32 +609,34 @@
 /* database existence has already been checked before now, might
  * have disappeared in the mean time (well, not really . . .)
  */
 struct sqlConnection *conn = hAllocConnMaybe(db);
 if (NULL == conn)
     apiErrAbort(err400, err400Msg, "can not find genome 'genome=%s' for endpoint '/getData/track", db);
 
 struct jsonWrite *jw = apiStartOutput();
 jsonWriteString(jw, "genome", db);
 
 // load the tracks
 struct trackDb *tdbList = NULL;
 cartTrackDbInitForApi(NULL, db, &tdbList, NULL, TRUE);
 
 // allow optional comma sep list of tracks
-char *tracks[100];
-int numTracks = chopByChar(trackArg, ',', tracks, sizeof(tracks));
+char *tracks[MAX_NUM_TRACKS+1];
+int numTracks = chopByChar(trackArg, ',', tracks, MAX_NUM_TRACKS+1);
+if (numTracks > MAX_NUM_TRACKS)
+    apiErrAbort(err400, err400Msg, "too many tracks requested, limit to 100 tracks or less for endpoint '/getData/track");
 int i = 0;
 struct hash *trackHash = hashNew(0); // let hub tracks work
 struct jsonWrite *columnTypesJw = NULL;
 if (jsonOutputArrays || debug)
     {
     columnTypesJw = jsonWriteNew();
     jsonWriteObjectStart(columnTypesJw, "columnTypes");
     }
 for (i = 0; i < numTracks; i++)
     {
     char *track = cloneString(tracks[i]);
     char *sqlTable = cloneString(track);
 
     if (cartTrackDbIsAccessDenied(db, sqlTable) ||
             (cartTrackDbIsNoGenome(db, sqlTable) && !(chrom && start && end)))