309f4ff097395a9427eca2bb956fc052bd1d596a
kent
  Tue Feb 26 17:24:59 2013 -0800
Fixing a bug that caused crashes and error messages on beds with lots of blocks.
diff --git src/lib/basicBed.c src/lib/basicBed.c
index 9da7425..f6137ed 100644
--- src/lib/basicBed.c
+++ src/lib/basicBed.c
@@ -1336,37 +1336,33 @@
 char *asStandardText = bedAsDef(15,15);
 asStandard = asParseText(asStandardText);
 result = asCompareObjs("Yours", asYours, "BED Standard", asStandard, numColumnsToCheck, NULL, abortOnDifference);
 freeMem(asStandardText);
 asObjectFreeList(&asStandard);
 return result;
 }
 
 
 void loadAndValidateBed(char *row[], int wordCount, int fieldCount, struct lineFile *lf, struct bed * bed, struct asObject *as, boolean isCt)
 /* Convert a row of strings to a bed and validate the contents.  Abort with message if invalid data. Optionally validate bedPlus via asObject.
  * If a customTrack, then some errors are tolerated. */
 {
 int count;
 int *blockSizes = NULL;
-int tempBlockSizes[1024];
 int *chromStarts;
-int tempChromStarts[1024];
 int *expIds;
-int tempExpIds[1024];
 float *expScores;
-float tempExpScores[1024];
 
 bed->chrom = row[0];  // note this value is not cloned for speed, callers may need to clone it.
 
 // This check is usually redundant since the caller should be checking it against actual chromInfo names
 // however hgLoadBed might not always have that info available.
 if (strlen(bed->chrom) >= BB_MAX_CHROM_STRING)  // must leave room for 0 terminator
     lineFileAbort(lf, "chrom [%s] is too long (must not exceed %d characters)", bed->chrom, BB_MAX_CHROM_STRING - 1);
 if (strlen(bed->chrom) < 1)
     lineFileAbort(lf, "chrom cannot be blank or empty");
 
 lineFileAllInts(lf, row, 1, &bed->chromStart, FALSE, 4, "integer", FALSE);
 
 lineFileAllInts(lf, row, 2, &bed->chromEnd, FALSE, 4, "integer", FALSE);
 
 if (bed->chromEnd < bed->chromStart)
@@ -1430,71 +1426,76 @@
 	int numColors = lineFileAllIntsArray(lf, row, 8, colors, sizeof colors, FALSE, 1, "integer", FALSE);
 	if (numColors == 3)
 	    {
 	    bed->itemRgb = (((unsigned)colors[0]) << 2*8) | (((unsigned)colors[1]) << 1*8) | (unsigned)colors[2];
 	    }
 	else
 	    lineFileAbort(lf, "Expecting color to consist of r,g,b values from 0 to 255. Got [%s]", saveColorString);
 	freeMem(saveColorString);
 	}
     else 
 	{
 	lineFileAllInts(lf, row, 8, &bed->itemRgb, FALSE, 4, "integer", FALSE);
 	}
     }
 
+int tempArraySize = 1;	// How big arrays are below
 if (wordCount > 9)
     {
     lineFileAllInts(lf, row, 9, &bed->blockCount, FALSE, 4, "integer", FALSE);
     if (!(bed->blockCount >= 1))
 	lineFileAbort(lf, "Expecting blockCount (%d) to be 1 or more.", bed->blockCount);
-    
+    tempArraySize = bed->blockCount;
     }
+int tempBlockSizes[tempArraySize];
+int tempChromStarts[tempArraySize];
+int tempExpIds[tempArraySize];
+float tempExpScores[tempArraySize];
 if (wordCount > 10)
     {
     if (isCt)
 	{
 	AllocArray(bed->blockSizes,bed->blockCount+1); // having +1 allows us to detect incorrect size
         count = lineFileAllIntsArray(lf, row, 10, bed->blockSizes, bed->blockCount+1, TRUE, 4, "integer", TRUE);
 	blockSizes = bed->blockSizes;
 	}
     else
 	{
-        count = lineFileAllIntsArray(lf, row, 10, tempBlockSizes, sizeof tempBlockSizes, TRUE, 4, "integer", TRUE);
+        count = lineFileAllIntsArray(lf, row, 10, tempBlockSizes, tempArraySize, TRUE, 4, "integer", TRUE);
 	blockSizes = tempBlockSizes;
 	}
     if (count != bed->blockCount)
 	lineFileAbort(lf, "Expecting %d elements in blockSizes list, found at least %d", bed->blockCount, count);
     int i;
     for (i=0; i < bed->blockCount;  i++)
 	{
         if (!(blockSizes[i] > 0))
 		lineFileAbort(lf, "BED blockSizes must be greater than 0, blockSize[%d] = %d", i, blockSizes[i]);
 	}
     }
 if (wordCount > 11)
     {
     int i;
     if (isCt)
 	{
 	AllocArray(bed->chromStarts,bed->blockCount+1); // having +1 allows us to detect incorrect size
         count = lineFileAllIntsArray(lf, row, 11, bed->chromStarts, bed->blockCount+1, TRUE, 4, "integer", TRUE);
 	chromStarts = bed->chromStarts;
 	}
     else
 	{
-        count = lineFileAllIntsArray(lf, row, 11, tempChromStarts, sizeof tempChromStarts, TRUE, 4, "integer", TRUE);
+        count = lineFileAllIntsArray(lf, row, 11, tempChromStarts, tempArraySize, TRUE, 4, "integer", TRUE);
 	chromStarts = tempChromStarts;
 	}
     if (count != bed->blockCount)
 	lineFileAbort(lf, "Expecting %d elements in chromStarts list, found at least %d", bed->blockCount, count);
     // tell the user if they appear to be using absolute starts rather than
     // relative... easy to forget!  Also check block order, coord ranges...
     if (chromStarts[0] != 0)
 	lineFileAbort(lf,
 	    "BED blocks must span chromStart to chromEnd.  "
 	    "BED chromStarts[0] = %d, must be 0 so that (chromStart + "
 	    "chromStarts[0]) equals chromStart.", chromStarts[0]);
 
     for (i=1; i < bed->blockCount;  i++)
 	{
 
@@ -1527,45 +1528,45 @@
 
 if (wordCount > 12)
     // get the microarray/colored-exon fields
     {
     lineFileAllInts(lf, row, 12, &bed->expCount, TRUE, 4, "integer", TRUE);
     if (!(bed->expCount >= 1))
 	lineFileAbort(lf, "Expecting expCount (%d) to be 1 or more.", bed->expCount);
     if (isCt)
 	{
 	AllocArray(bed->expIds,bed->expCount+1); // having +1 allows us to detect incorrect size
         count = lineFileAllIntsArray(lf, row, 13, bed->expIds, bed->expCount+1, TRUE, 4, "integer", TRUE);
 	expIds = bed->expIds;
 	}
     else
 	{
-        count = lineFileAllIntsArray(lf, row, 13, tempExpIds, sizeof tempExpIds, TRUE, 4, "integer", TRUE);
+        count = lineFileAllIntsArray(lf, row, 13, tempExpIds, tempArraySize, TRUE, 4, "integer", TRUE);
 	expIds = tempExpIds;
 	}
     if (count != bed->expCount)
 	lineFileAbort(lf, "expecting %d elements in expIds list (bed field 14)", bed->expCount);
     if (wordCount == 15)
 	{
 	if (isCt)
 	    {
 	    sqlFloatDynamicArray(row[14], &bed->expScores, &count);
 	    expScores = bed->expScores;
 	    }
 	else
 	    {
-	    count = sqlFloatArray(row[14], tempExpScores, sizeof tempExpScores);
+	    count = sqlFloatArray(row[14], tempExpScores, tempArraySize);
 	    expScores = tempExpScores;
 	    }
 	if (count != bed->expCount)
 	    lineFileAbort(lf, "expecting %d elements in expScores list (bed field 15)", bed->expCount);
 	}
     }
 
 /* Check bedPlus fields are formatted right. */
 /* This could form the basis of an .as-validator independent of BED. I suppose it could go in asParse.c */
 if (as)
     {
     struct hash* linkHash = NULL;
     /* Validate as-fields */
     struct asColumn *asCol = NULL;
     asCol = as->columnList;