Skip to content

Commit b8863d7

Browse files
committed
Merge version number bump and NEWS file from master
2 parents 4f08744 + d1a2a87 commit b8863d7

File tree

11 files changed

+191
-72
lines changed

11 files changed

+191
-72
lines changed

NEWS

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,54 @@
11
Noteworthy changes in release a.b
22
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33

4+
Noteworthy changes in release 1.23.1 (18th March 2026)
5+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6+
7+
Bug fixes
8+
---------
9+
10+
* Fix a number of bugs in the CRAM decoder which could result in undefined
11+
behaviour on invalid inputs (PR #1981, PR #1991):
12+
13+
- Not checking the amount of byte array len data returned matched the amount
14+
expected. (CVE-2026-31971)
15+
- Incorrect check for the length of byte array stop data. (CVE-2026-31969)
16+
- Invalid use of the varint and const codecs. (CVE-2026-31968)
17+
- Missing check for a valid reference ID. (CVE-2026-31965)
18+
- Missing check for a valid mate reference ID. (CVE-2026-31967)
19+
- Incomplete validation of CRAM feature locations.
20+
(CVE-2026-31965, CVE-2026-31966)
21+
- Bugs due to improper handling of records where no sequence or quality
22+
values were stored (CVE-2026-31962, CVE-2026-31964)
23+
24+
* Reject GZI indexes with impossibly-large item counts. (CVE-2026-31970)
25+
(PR #1978. Reported by Harrison Green)
26+
27+
* Prevent the wrong item count from being written to GZI indexes of
28+
empty files.
29+
(PR #1988. Reported by Matthieu Muffato)
30+
31+
* Fix invalid behaviour if kmemmem(), kstrstr() or kstrnstr() were
32+
called with a zero-length pattern, or if kstrstr() was given a very
33+
long input. Also ensure they can never fail by supplying a fallback
34+
algorithm that does not allocate any memory.
35+
(PR #1980. Reported by Harrison Green)
36+
37+
* Prevent redundant copies of hash keys in string pools.
38+
(PR #1982)
39+
40+
* Fix regressions in the S3 plugin which caused uploads to fail.
41+
(PR #1984)
42+
43+
* Disallow attempts to set the thread pool attached to an htsFile twice.
44+
(PR #1985)
45+
46+
Build Changes
47+
-------------
48+
49+
* The htscodecs submodule is updated to v1.6.6.
50+
(PR #1989)
51+
452
Noteworthy changes in release 1.23 (16th December 2025)
553
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
654

annot-tsv.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'\" t
2-
.TH annot-tsv 1 "16 December 2025" "htslib-1.23" "Bioinformatics tools"
2+
.TH annot-tsv 1 "18 March 2026" "htslib-1.23.1" "Bioinformatics tools"
33
.\"
44
.\" Copyright (C) 2015, 2017-2018, 2023-2024 Genome Research Ltd.
55
.\"

bgzip.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.TH bgzip 1 "16 December 2025" "htslib-1.23" "Bioinformatics tools"
1+
.TH bgzip 1 "18 March 2026" "htslib-1.23.1" "Bioinformatics tools"
22
.SH NAME
33
.PP
44
bgzip \- Block compression/decompression utility

cram/cram_codecs.c

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2012-2021,2023, 2025 Genome Research Ltd.
2+
Copyright (c) 2012-2021,2023, 2025, 2026 Genome Research Ltd.
33
Author: James Bonfield <jkb@sanger.ac.uk>
44
55
Redistribution and use in source and binary forms, with or without
@@ -776,17 +776,23 @@ cram_codec *cram_varint_decode_init(cram_block_compression_hdr *hdr,
776776
// does not change.
777777
switch(codec) {
778778
case E_VARINT_UNSIGNED:
779-
c->decode = (option == E_INT)
780-
? cram_varint_decode_int
781-
: cram_varint_decode_long;
779+
if (option == E_INT || option == E_SINT)
780+
c->decode = cram_varint_decode_int;
781+
else if (option == E_LONG || option == E_SLONG)
782+
c->decode = cram_varint_decode_long;
783+
else
784+
goto malformed;
782785
break;
783786
case E_VARINT_SIGNED:
784-
c->decode = (option == E_INT)
785-
? cram_varint_decode_sint
786-
: cram_varint_decode_slong;
787+
if (option == E_INT || option == E_SINT)
788+
c->decode = cram_varint_decode_sint;
789+
else if (option == E_LONG || option == E_SLONG)
790+
c->decode = cram_varint_decode_slong;
791+
else
792+
goto malformed;
787793
break;
788794
default:
789-
return NULL;
795+
goto malformed;
790796
}
791797

792798
c->free = cram_varint_decode_free;
@@ -798,14 +804,17 @@ cram_codec *cram_varint_decode_init(cram_block_compression_hdr *hdr,
798804
c->u.varint.offset = vv->varint_get64s(&cp, cp_end, NULL);
799805

800806
if (cp - data != size) {
801-
fprintf(stderr, "Malformed varint header stream\n");
802-
free(c);
803-
return NULL;
807+
goto malformed;
804808
}
805809

806810
c->u.varint.type = option;
807811

808812
return c;
813+
814+
malformed:
815+
hts_log_error("Malformed varint header stream");
816+
free(c);
817+
return NULL;
809818
}
810819

811820
int cram_varint_encode_int(cram_slice *slice, cram_codec *c,
@@ -924,6 +933,9 @@ int cram_const_decode_byte(cram_slice *slice, cram_codec *c,
924933
cram_block *in, char *out, int *out_size) {
925934
int i, n;
926935

936+
if (!out)
937+
return 0;
938+
927939
for (i = 0, n = *out_size; i < n; i++)
928940
out[i] = c->u.xconst.val;
929941

@@ -978,12 +990,17 @@ cram_codec *cram_const_decode_init(cram_block_compression_hdr *hdr,
978990
return NULL;
979991

980992
c->codec = codec;
981-
if (codec == E_CONST_BYTE)
993+
if (codec == E_CONST_BYTE && option == E_BYTE)
982994
c->decode = cram_const_decode_byte;
983-
else if (option == E_INT)
995+
else if (codec == E_CONST_INT && (option == E_INT || option == E_SINT))
984996
c->decode = cram_const_decode_int;
985-
else
997+
else if (codec == E_CONST_INT && (option == E_LONG || option == E_SLONG))
986998
c->decode = cram_const_decode_long;
999+
else {
1000+
hts_log_error("Malformed const header stream");
1001+
free(c);
1002+
return NULL;
1003+
}
9871004
c->free = cram_const_decode_free;
9881005
c->size = cram_const_decode_size;
9891006
c->get_block = NULL;
@@ -1404,7 +1421,7 @@ int cram_xpack_decode_char(cram_slice *slice, cram_codec *c, cram_block *in, cha
14041421
if (out)
14051422
memcpy(out, b->data + b->byte, *out_size);
14061423
b->byte += *out_size;
1407-
} else {
1424+
} else if (out) {
14081425
memset(out, c->u.xpack.rmap[0], *out_size);
14091426
}
14101427

@@ -2111,7 +2128,8 @@ int cram_xrle_decode_char(cram_slice *slice, cram_codec *c, cram_block *in, char
21112128
cram_xrle_decode_expand_char(slice, c);
21122129
cram_block *b = slice->block_by_id[512 + c->codec_id];
21132130

2114-
memcpy(out, b->data + b->idx, n);
2131+
if (out)
2132+
memcpy(out, b->data + b->idx, n);
21152133
b->idx += n;
21162134
return 0;
21172135

@@ -3568,7 +3586,7 @@ cram_codec *cram_byte_array_len_encode_init(cram_stats *st,
35683586
static int cram_byte_array_stop_decode_char(cram_slice *slice, cram_codec *c,
35693587
cram_block *in, char *out,
35703588
int *out_size) {
3571-
char *cp, ch;
3589+
uint8_t *cp;
35723590
cram_block *b = NULL;
35733591

35743592
b = cram_get_block_by_id(slice, c->u.byte_array_stop.content_id);
@@ -3578,31 +3596,29 @@ static int cram_byte_array_stop_decode_char(cram_slice *slice, cram_codec *c,
35783596
if (b->idx >= b->uncomp_size)
35793597
return -1;
35803598

3581-
cp = (char *)b->data + b->idx;
3599+
ssize_t term = b->uncomp_size - b->idx;
3600+
cp = b->data + b->idx;
35823601
if (out) {
35833602
// memccpy equivalent but without copying the terminating byte
3584-
ssize_t term = MIN(*out_size, b->uncomp_size - b->idx);
3585-
while ((ch = *cp) != (char)c->u.byte_array_stop.stop) {
3586-
if (term-- < 0)
3587-
break;
3588-
*out++ = ch;
3589-
cp++;
3603+
if (term > *out_size)
3604+
term = *out_size;
3605+
while (--term >= 0 && *cp != c->u.byte_array_stop.stop) {
3606+
*out++ = *cp++;
35903607
}
35913608

3592-
// Attempted overrun on input or output
3593-
if (ch != (char)c->u.byte_array_stop.stop)
3594-
return -1;
35953609
} else {
35963610
// Consume input, but produce no output
3597-
while ((ch = *cp) != (char)c->u.byte_array_stop.stop) {
3598-
if (cp - (char *)b->data >= b->uncomp_size)
3599-
return -1;
3611+
while (--term >= 0 && *cp != c->u.byte_array_stop.stop) {
36003612
cp++;
36013613
}
36023614
}
36033615

3604-
*out_size = cp - (char *)(b->data + b->idx);
3605-
b->idx = cp - (char *)b->data + 1;
3616+
// Attempted overrun on input or output
3617+
if (cp >= b->data + b->uncomp_size || *cp != c->u.byte_array_stop.stop)
3618+
return -1;
3619+
3620+
*out_size = cp - (b->data + b->idx);
3621+
b->idx = cp - b->data + 1;
36063622

36073623
return 0;
36083624
}

0 commit comments

Comments
 (0)