Skip to content

Commit

Permalink
Fix cram_encode fuzzer issue caused by negative reference lengths.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jkbonfield committed Dec 9, 2024
1 parent a662866 commit c705bec
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 2 deletions.
4 changes: 4 additions & 0 deletions cram/cram_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3247,6 +3247,10 @@ cram_slice *cram_next_slice(cram_fd *fd, cram_container **cp) {
if (fd->ooc)
break;

// printf("%p %d:%ld-%ld vs %d:%ld-%ld\n", fd,
// c_next->ref_seq_id, c_next->ref_seq_start, c_next->ref_seq_start+c_next->ref_seq_span-1,
// fd->range.refid, fd->range.start, fd->range.end);

/* Skip containers not yet spanning our range */
if (fd->range.refid != -2 && c_next->ref_seq_id != -2) {
// ref_id beyond end of range; bail out
Expand Down
3 changes: 2 additions & 1 deletion cram/cram_encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3691,7 +3691,8 @@ static int process_one_read(cram_fd *fd, cram_container *c,
return -1;
}
fake_qual = spos;
cr->aend = no_ref ? apos : MIN(apos, c->ref_end);
// Protect against negative length refs (fuzz 382922241)
cr->aend = no_ref ? apos : MIN(apos, MAX(0, c->ref_end));
if (cram_stats_add(c->stats[DS_FN], cr->nfeature) < 0)
goto block_err;

Expand Down
8 changes: 7 additions & 1 deletion cram/cram_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2790,9 +2790,13 @@ static int refs_from_header(cram_fd *fd) {
if ((tag = sam_hrecs_find_key(ty, "M5", NULL)))
r->ref_id[j]->fn = string_dup(r->pool, tag->str+3);

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

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

0 comments on commit c705bec

Please sign in to comment.