Skip to content

Commit 2d168cd

Browse files
committed
fix a fasta segfault
1 parent 6db5d39 commit 2d168cd

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

src/faidx/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ impl Reader {
161161

162162
/// Fetches the i-th sequence name.
163163
pub fn seq_name(&self, i: i32) -> Result<String, FaidxError> {
164+
// faidx_iseq does no bounds checking (it indexes directly into an
165+
// array), so we must validate the index before calling it.
166+
if i < 0 || (i as u64) >= self.n_seqs() {
167+
return Err(FaidxError::InvalidSequenceName { index: i });
168+
}
164169
let ptr = unsafe { htslib::faidx_iseq(self.inner, i) };
165170
if ptr.is_null() {
166171
return Err(FaidxError::InvalidSequenceName { index: i });
@@ -324,6 +329,40 @@ mod tests {
324329
assert_eq!(n, "chr2");
325330
}
326331

332+
#[test]
333+
fn faidx_seq_name_all_valid_indices() {
334+
let r = open_reader();
335+
assert_eq!(r.seq_name(0).unwrap(), "chr1");
336+
assert_eq!(r.seq_name(1).unwrap(), "chr2");
337+
assert_eq!(r.seq_name(2).unwrap(), "chr3");
338+
}
339+
340+
#[test]
341+
fn faidx_seq_name_boundary() {
342+
// n_seqs() == 3, so index 2 is the last valid and 3 is the first invalid.
343+
// faidx_iseq does no bounds checking in C, so calling it with an
344+
// out-of-bounds index would segfault without our Rust-side guard.
345+
let r = open_reader();
346+
assert!(r.seq_name(2).is_ok());
347+
assert!(matches!(
348+
r.seq_name(3),
349+
Err(FaidxError::InvalidSequenceName { index: 3 })
350+
));
351+
}
352+
353+
#[test]
354+
fn faidx_seq_name_i32_extremes() {
355+
let r = open_reader();
356+
assert!(matches!(
357+
r.seq_name(i32::MAX),
358+
Err(FaidxError::InvalidSequenceName { index: i32::MAX })
359+
));
360+
assert!(matches!(
361+
r.seq_name(i32::MIN),
362+
Err(FaidxError::InvalidSequenceName { index: i32::MIN })
363+
));
364+
}
365+
327366
#[test]
328367
fn faidx_get_seq_len() {
329368
let r = open_reader();

0 commit comments

Comments
 (0)