Skip to content

Commit c705bec

Browse files
committed
Fix cram_encode fuzzer issue caused by negative reference lengths.
Introduced in 24e4e31 with the cache of the LN_length field. We now validate this as positive. The check in cram_encode.c should now not be necessary, but it's fixed in two places incase we ever get this cropping up via another route. Credit to OSS_Fuzz Fixes oss-fuzz issue 382922241
1 parent a662866 commit c705bec

File tree

3 files changed

+13
-2
lines changed

3 files changed

+13
-2
lines changed

cram/cram_decode.c

+4
Original file line numberDiff line numberDiff line change
@@ -3247,6 +3247,10 @@ cram_slice *cram_next_slice(cram_fd *fd, cram_container **cp) {
32473247
if (fd->ooc)
32483248
break;
32493249

3250+
// printf("%p %d:%ld-%ld vs %d:%ld-%ld\n", fd,
3251+
// c_next->ref_seq_id, c_next->ref_seq_start, c_next->ref_seq_start+c_next->ref_seq_span-1,
3252+
// fd->range.refid, fd->range.start, fd->range.end);
3253+
32503254
/* Skip containers not yet spanning our range */
32513255
if (fd->range.refid != -2 && c_next->ref_seq_id != -2) {
32523256
// ref_id beyond end of range; bail out

cram/cram_encode.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -3691,7 +3691,8 @@ static int process_one_read(cram_fd *fd, cram_container *c,
36913691
return -1;
36923692
}
36933693
fake_qual = spos;
3694-
cr->aend = no_ref ? apos : MIN(apos, c->ref_end);
3694+
// Protect against negative length refs (fuzz 382922241)
3695+
cr->aend = no_ref ? apos : MIN(apos, MAX(0, c->ref_end));
36953696
if (cram_stats_add(c->stats[DS_FN], cr->nfeature) < 0)
36963697
goto block_err;
36973698

cram/cram_io.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -2790,9 +2790,13 @@ static int refs_from_header(cram_fd *fd) {
27902790
if ((tag = sam_hrecs_find_key(ty, "M5", NULL)))
27912791
r->ref_id[j]->fn = string_dup(r->pool, tag->str+3);
27922792

2793-
if ((tag = sam_hrecs_find_key(ty, "LN", NULL)))
2793+
if ((tag = sam_hrecs_find_key(ty, "LN", NULL))) {
27942794
// LN tag used when constructing consensus reference
27952795
r->ref_id[j]->LN_length = strtoll(tag->str+3, NULL, 0);
2796+
// See fuzz 382922241
2797+
if (r->ref_id[j]->LN_length < 0)
2798+
r->ref_id[j]->LN_length = 0;
2799+
}
27962800
}
27972801

27982802
k = kh_put(refs, r->h_meta, r->ref_id[j]->name, &n);
@@ -5818,6 +5822,8 @@ int cram_set_voption(cram_fd *fd, enum hts_fmt_option opt, va_list args) {
58185822
case CRAM_OPT_RANGE: {
58195823
int r = cram_seek_to_refpos(fd, va_arg(args, cram_range *));
58205824
pthread_mutex_lock(&fd->range_lock);
5825+
// printf("opt range noseek to %p %d:%ld-%ld\n",
5826+
// fd, fd->range.refid, fd->range.start, fd->range.end);
58215827
if (fd->range.refid != -2)
58225828
fd->required_fields |= SAM_POS;
58235829
pthread_mutex_unlock(&fd->range_lock);

0 commit comments

Comments
 (0)