From b617ed7fe91b776291c5fa339e4ae3be9ae497ef Mon Sep 17 00:00:00 2001 From: James Bonfield Date: Wed, 8 Apr 2026 10:19:57 +0100 Subject: [PATCH 1/2] Fix extend_ref to not change ref_end on error. If we fail to extend the buffer, we shouldn't extend ref_end. This avoids needing to check downstream everywhere we use ref_end to make sure it's not bigger than ref_end_alloc. Instead we'll just get short references and need to encode overhanging sequences against Ns. Credit to OSS_Fuzz Fixes oss-fuzz issue 499447432 --- cram/cram_encode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cram/cram_encode.c b/cram/cram_encode.c index 735784e89..00d2e48e0 100644 --- a/cram/cram_encode.c +++ b/cram/cram_encode.c @@ -1504,7 +1504,7 @@ int next_cigar_op(uint32_t *cigar, uint32_t ncigar, int *skip, int *spos, static inline int extend_ref(char **ref, uint32_t (**hist)[5], hts_pos_t pos, hts_pos_t ref_start, hts_pos_t *ref_end, hts_pos_t *ref_end_alloc) { - if (*ref_end < pos) + if (*ref_end < pos && pos < *ref_end_alloc) *ref_end = pos; if (pos < ref_start) return -1; @@ -1542,6 +1542,9 @@ static inline int extend_ref(char **ref, uint32_t (**hist)[5], hts_pos_t pos, memset(&(*ref)[old_end], 0, new_end-old_end); memset(&(*hist)[old_end], 0, (new_end-old_end)*sizeof(**hist)); + if (*ref_end < pos) + *ref_end = pos; + return 0; } From 490b3b38102ff4f64dc86827e835d4f83566e1f6 Mon Sep 17 00:00:00 2001 From: James Bonfield Date: Mon, 13 Apr 2026 11:36:26 +0100 Subject: [PATCH 2/2] Improve SQ LN field checking. Converting a file to CRAM with embed_ref=2 and SQ LN:0 triggers some unusual code paths because we use a non-zero length field as an indicator for the referencing having been populated. In this case we convert sequence to Ns (albeit not overflowing buffers and in a secure way). However it's a wider issue. LN:-2 was permitted and it gets convered to MAX_INT in bam. Plus "LN:" (no length) was accepted and treated as zero. So instead of putting the fix in cram_io.c refs_from_header() ("if (h->hrecs->ref[i].len <= 0) ...") we disallow this globally for all file formats. --- header.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/header.c b/header.c index ec5f266b9..d4f39cda6 100644 --- a/header.c +++ b/header.c @@ -174,8 +174,8 @@ static int sam_hrecs_update_hashes(sam_hrecs_t *hrecs, return -1; // SN should be present, according to spec. } - if (len == -1) { - hts_log_error("Header includes @SQ line \"%s\" with no LN: tag", + if (len <= 0) { + hts_log_error("Header includes @SQ line \"%s\" with invalid or no LN: tag", name); return -1; // LN should be present, according to spec. }