message: fix: avoid buffer overflow by using positions relative to the gene start
diff: @@ -35,8 +35,13 @@ export function reconstructGeneSequences(
  // Implant substitutions from query sequence
  for (const mut of mutations) {
  const { pos, queryNuc } = mut
  - if (inRange(pos, geneBegin, geneEnd)) {
  - queryGene[pos] = queryNuc
  +
  + if (inRange(pos, gene.range)) {
  + const genePos = geneBegin - pos // Position relative to the gene start
  +
  + // TODO: invariant(genePos > 0)
  + // TODO: invariant(genePos < queryGene.length)
  + queryGene[genePos] = queryNuc
  }
  }
  @@ -49,16 +54,20 @@ export function reconstructGeneSequences(
  const end = Math.min(geneEnd, delEnd)
  // TODO: invariant(begin > 0)
  - // TODO: invariant(begin < queryGene.length)
  - // TODO: invariant(end < queryGene.length)
  + // TODO: invariant(begin <= end)
  + // TODO: invariant(end - begin <= queryGene.length)
  // Fill deletion range with gaps
  - for (let i = begin; i < end; ++i) {
  - queryGene[i] = AMINOACID_GAP
  + for (let pos = begin; pos < end; ++pos) {
  + const genePos = geneBegin - pos // Position relative to the gene start
  + // TODO: invariant(genePos > 0)
  + // TODO: invariant(genePos < queryGene.length)
  + queryGene[genePos] = AMINOACID_GAP
  }
  }
  // TODO: postcondition(isDivisibleBy(queryGene.length, 3))
  + // TODO: postcondition(refGene.length, initialLength))
  // TODO: postcondition(queryGene.length, initialLength))
  return { refGene: refGene.join(''), queryGene: queryGene.join('') }
  }
  @@ -70,8 +79,8 @@ export function addAminoacidChanges(
  aaSubstitutions: AminoacidSubstitution[],
  aaDeletions: AminoacidDeletion[],
  ) {
  + // TODO: precondition(queryGene == refGene)
  // TODO: precondition(isDivisibleBy(refGene.length, 3))
  - // TODO: precondition(isDivisibleBy(queryGene.length, 3))
  const { begin } = gene.range
  @@ -99,7 +108,7 @@ export function associateSubstitutions(mutations: NucleotideSubstitution[], aaSu
  return mutations.map((mut) => {
  const theseAaSubstitutions = aaSubstitutions.filter((aaSub) =>
  // Nuc substitution causes AA substitution iff its position is in the codon range
  - inRange(mut.pos, aaSub.nucRange.begin, aaSub.nucRange.end),
  + inRange(mut.pos, aaSub.nucRange),
  )
  return { ...mut, aaSubstitutions: theseAaSubstitutions }
  })
  