01fbc2b46b7fe918aa6628cca8ca8ee7ede0e598 braney Wed Aug 19 17:54:38 2026 -0700 pgSnp: replace a fixed-size local array in alleleCountsFromVcfRecord with an allocation sized from the record, refs #38154 diff --git src/hg/lib/pgSnp.c src/hg/lib/pgSnp.c index c383e196419..950bde5f750 100644 --- src/hg/lib/pgSnp.c +++ src/hg/lib/pgSnp.c @@ -722,49 +722,51 @@ row[3], item->alleleCount); /* read count, comma separated list of numbers with above # of items */ item->alleleFreq = cloneString(row[5]); char pattern[128]; safef(pattern, sizeof(pattern), "^[0-9]+(,[0-9]+){%d}$", item->alleleCount - 1); if (! regexMatchNoCase(row[5], pattern)) lineFileAbort(lf, "invalid allele frequency, %s with count of %d", row[5], item->alleleCount); /* scores, comma separated list of numbers with above # of items */ item->alleleScores = cloneString(row[6]); safef(pattern, sizeof(pattern), "^[0-9.]+(,[0-9.]+){%d}$", item->alleleCount - 1); if (! regexMatchNoCase(row[6], pattern)) lineFileAbort(lf, "invalid allele scores, %s with count of %d", row[6], item->alleleCount); return item; } -#define VCF_MAX_ALLELE_LEN 80 - static char *alleleCountsFromVcfTumorAd(const struct vcfInfoElement *ad) /* Build up comma-sep list of read counts supporting tumor alleles */ { struct dyString *dy = dyStringNew(0); // Assume only one alternate allele int r = ad->values[0].datInt; int a = ad->values[1].datInt; dyStringPrintf(dy, "%d,%d", r, a); return dyStringCannibalize(&dy); } static char *alleleCountsFromVcfRecord(struct vcfRecord *rec, int alDescCount) /* Build up comma-sep list of per-allele counts, if available, up to alDescCount * which may be less than rec->alleleCount: */ { struct dyString *dy = dyStringNew(0); -int alCounts[VCF_MAX_ALLELE_LEN]; +// Repeat sites can have hundreds of alleles, so size this by the record instead of +// using a fixed-size array. +int alCountSize = max(alDescCount, rec->alleleCount) + 1; +int *alCounts = NULL; +AllocArray(alCounts, alCountSize); boolean gotTotalCount = FALSE, gotAltCounts = FALSE; int i; for (i = 0; i < rec->infoCount; i++) if (sameString(rec->infoElements[i].key, "AN")) { if (rec->infoElements[i].missingData[0]) break; gotTotalCount = TRUE; // Set ref allele to total count, subtract alt counts below. alCounts[0] = rec->infoElements[i].values[0].datInt; break; } for (i = 0; i < rec->infoCount; i++) if (sameString(rec->infoElements[i].key, "AC")) { @@ -846,30 +848,31 @@ alCounts[i] = 0; for (i = 0; i < rec->file->genotypeCount; i++) { struct vcfGenotype *gt = &(rec->genotypes[i]); if (gt == NULL) uglyf("i=%d gt=NULL wtf?\n", i); if (gt->hapIxA >= 0) alCounts[(unsigned char)gt->hapIxA]++; if (!gt->isHaploid && gt->hapIxB >= 0) alCounts[(unsigned char)gt->hapIxB]++; } dyStringPrintf(dy, "%d", alCounts[0]); for (i = 1; i < alDescCount; i++) dyStringPrintf(dy, ",%d", alCounts[i]); } +freeMem(alCounts); return dyStringCannibalize(&dy); } static void pgSnpFromVcfSgtIndelRecord(struct vcfRecord *rec, struct pgSnp *pgs) /* parse alleles and frequency from vcf file with SGT for indels */ { pgs->alleleCount = 2; // assume always 2: normal->tumor struct dyString *dy = dyStringCreate("%s/%s", rec->alleles[0], rec->alleles[1]); pgs->name = dyStringCannibalize(&dy); int refCnt = -1, altCnt = -1; const struct vcfGenotype *gt = vcfRecordFindGenotype(rec, "TUMOR"); if (gt) { const struct vcfInfoElement *dp = vcfGenotypeFindInfo(gt, "DP"); const struct vcfInfoElement *tar = vcfGenotypeFindInfo(gt, "TAR");