6c676a0e9ed642676008731762141e0c16822787 braney Sat Aug 22 09:31:14 2026 -0700 vcf: tighten validation of the genotype allele index, refs #38155 New parseAlleleIx returns missing data for a GT allele index that the record has no allele for, and for a value that will not fit the field. It checks the value as an int, before it reaches the field. vcfParseGenotypes and vcfParseGenotypesGtOnly both go through it, and a check after the per-genotype loop covers the PL and SGT fallbacks, which choose an index without consulting the allele count. hapIxA and hapIxB become signed char. Plain char is unsigned on some architectures, and the negative missing-data value did not stay negative there. Size and field offsets are unchanged, and x86 code generation is identical. Adds a lib/tests case for malformed and boundary genotype indexes. diff --git src/inc/vcf.h src/inc/vcf.h index e5f210e80fd..f83e273dc66 100644 --- src/inc/vcf.h +++ src/inc/vcf.h @@ -44,33 +44,35 @@ }; struct vcfInfoElement /* A single INFO column component; each row's INFO column may contain multiple components. */ { char *key; // An identifier described by a struct vcfInfoDef int count; // Number of data values following id union vcfDatum *values; // Array of data values following id bool *missingData; // Array of flags for missing data values ("." instead of number) }; struct vcfGenotype /* A single component of the optional GENOTYPE column. */ { char *id; // Name of individual/sample (pointer to vcfFile genotypeIds) or . - char hapIxA; // Index of one haplotype's allele: 0=reference, 1=alt, 2=other alt - // *or* if negative, missing data - char hapIxB; // Index of other haplotype's allele, or if negative, missing data + signed char hapIxA; // Index of one haplotype's allele: 0=reference, 1=alt, 2=other alt + // *or* if negative, missing data. Explicitly signed: plain char is + // unsigned on some architectures, and the missing-data value has to + // stay negative there too. + signed char hapIxB; // Index of other haplotype's allele, or if negative, missing data bool isPhased; // True if haplotypes are phased bool isHaploid; // True if there is only one haplotype (e.g. chrY) int infoCount; // Number of components named in FORMAT column struct vcfInfoElement *infoElements; // Array of info components for this genotype call }; struct vcfRecord /* A VCF data row (or list of rows). */ { struct vcfRecord *next; char *chrom; // Reference assembly sequence name unsigned int chromStart; // Start offset in chrom unsigned int chromEnd; // End offset in chrom char *name; // Variant name from ID column int alleleCount; // Number of alleles (reference + alternates)