Skip to content

panic in index_stats for tid = -1 #490

@wdecoster

Description

@wdecoster

Hi,

I came across the following error with code using rust-htslib, which I narrowed down to a call of the index_stats() function:

thread 'main' panicked at /home/wdecoster/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rust-htslib-0.50.0/src/bam/mod.rs:849:47:
index out of bounds: the len is 196 but the index is 18446744073709551615
stack backtrace:
   0:     0x55724815a5d2 - <unknown>
   1:     0x55724804dc23 - <unknown>
   2:     0x557248159fef - <unknown>
   3:     0x55724815a433 - <unknown>
   4:     0x557248159b05 - <unknown>
   5:     0x55724818ecf8 - <unknown>
   6:     0x55724818ec59 - <unknown>
   7:     0x55724818f43c - <unknown>
   8:     0x55724804bd6f - <unknown>
   9:     0x55724804bd4c - <unknown>
  10:     0x557248150a54 - <unknown>
  11:     0x557247fb8ec1 - <unknown>
  12:     0x557247fc5021 - <unknown>
  13:     0x557247f3f8b3 - <unknown>
  14:     0x557247fe1851 - <unknown>
  15:     0x7ff71a4295d0 - __libc_start_call_main
  16:     0x7ff71a429680 - __libc_start_main@GLIBC_2.2.5
  17:     0x557247f2772e - <unknown>
  18:                0x0 - <unknown>
Aborted (core dumped)

The error appears to be (with some help of copilot...) on lines 845 and 849 in src/bam/mod.rs. Both lines cast tid directly to usize without handling tid == -1 (for unmapped reads) when casting to usize.

// PRESUMABLY BUGGY CODE (lines 844-849):
if tid != last_tid {
    if (last_tid >= -1) && (counts[tid as usize][0] + counts[tid as usize][1]) > 0 {  // BUG: tid can be -1
        return Err(Error::BamUnsorted);
    }
    last_tid = tid;
}

let idx = if ((*b).core.flag as u32 & hts_sys::BAM_FUNMAP) > 0 {
    1
} else {
    0
};
counts[(*b).core.tid as usize][idx] += 1;  // BUG: (*b).core.tid can be -1

Below is also a proposed fix. I can open a PR if that looks alright?

if tid != last_tid {
    let array_idx = if tid == -1 { nref } else { tid as usize };
    if (last_tid >= -1) && (counts[array_idx][0] + counts[array_idx][1]) > 0 {
        return Err(Error::BamUnsorted);
    }
    last_tid = tid;
}

let idx = if ((*b).core.flag as u32 & hts_sys::BAM_FUNMAP) > 0 {
    1
} else {
    0
};
let array_idx = if (*b).core.tid == -1 { nref } else { (*b).core.tid as usize };
counts[array_idx][idx] += 1;// FIXED CODE:
if tid != last_tid {
    let array_idx = if tid == -1 { nref } else { tid as usize };
    if (last_tid >= -1) && (counts[array_idx][0] + counts[array_idx][1]) > 0 {
        return Err(Error::BamUnsorted);
    }
    last_tid = tid;
}

let idx = if ((*b).core.flag as u32 & hts_sys::BAM_FUNMAP) > 0 {
    1
} else {
    0
};
let array_idx = if (*b).core.tid == -1 { nref } else { (*b).core.tid as usize };
counts[array_idx][idx] += 1;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions