83c50d3af3614ea3832bbea7c95488296d0b392e
jcasper
  Mon Nov 4 07:17:51 2024 -0800
When parsing a BED, the space allocated for expScores should be at least expCount
entries, even if that's greater than the number of exons. #12101

diff --git src/lib/basicBed.c src/lib/basicBed.c
index 3251f15..b39de3f 100644
--- src/lib/basicBed.c
+++ src/lib/basicBed.c
@@ -1553,30 +1553,41 @@
     else 
 	{
 	lineFileAllInts(lf, row, 8, &bed->itemRgb, FALSE, 4, "integer", FALSE);
 	}
     }
 
 int tempArraySize = 1;	// How big arrays are below
 if (bedFieldCount > 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;
     }
 
+if (bedFieldCount > 12)
+    // get the microarray/colored-exon field count; we might need to increase tempArraySize
+    // if expCount > blockCount, since the allocated array is used for both exons and expScores
+    {
+    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 && bed->expCount > tempArraySize)
+        tempArraySize = bed->expCount;
+    }
+
 // this memory never gets freed, but tempArraySize can be huge so
 // we can't allocate it off the stack and we don't want to be 
 // allocating and freeing it millions of times on huge beds.
 char *allocatedMem = getScratchMem(3 * tempArraySize * sizeof(int) + tempArraySize * sizeof(float));
 int *tempBlockSizes = (int *)allocatedMem;
 int *tempChromStarts = (int *)&allocatedMem[tempArraySize * sizeof(int)];
 int *tempExpIds = (int *)&allocatedMem[2*tempArraySize * sizeof(int)];
 float *tempExpScores = (float *)&allocatedMem[3*tempArraySize * sizeof(int)];
 
 if (bedFieldCount > 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);
@@ -1643,33 +1654,30 @@
         if (allow1bpOverlap)
             fudge = -1;
         if (!(chromStarts[i] >= chromStarts[i-1] + blockSizes[i-1] + fudge))
 		lineFileAbort(lf, "BED blocks must be in ascending order without overlap. Blocks %d and %d overlap.", i-1, i);
 	}
 
     // last block-end must match chromEnd
     i = bed->blockCount-1;
     if ((bed->chromStart + chromStarts[i] + blockSizes[i]) != bed->chromEnd)
 	lineFileAbort(lf, BAD_BLOCKS);
     }
 
 if (bedFieldCount > 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);
 	}
     else
 	{
         count = lineFileAllIntsArray(lf, row, 13, tempExpIds, tempArraySize, TRUE, 4, "integer", TRUE);
 	}
     if (count != bed->expCount)
 	lineFileAbort(lf, "expecting %d elements in expIds list (bed field 14)", bed->expCount);
     if (bedFieldCount == 15)
 	{
 	if (isCt)
 	    {