Description:
quick_xml::events::attributes::Attributes::new(buf, pos) documents that if pos is greater than the buffer length, the iterator should immediately return None. However, when such an Attributes iterator is consumed, either directly via next() or indirectly via has_nil(), it panics due to an out-of-bounds slice access.
Environment:
quick-xml version: 0.41.0
rustc version: 1.94.1
OS: Ubuntu 20.04.6 LTS
Command: RUST_BACKTRACE=full cargo run
PoC
use quick_xml::events::attributes::Attributes;
use quick_xml::reader::NsReader;
fn main() {
let mut attrs = Attributes::new("a", 2);
let reader = NsReader::from_str("");
let _ = attrs.has_nil(reader.resolver());
}
Expected behavior:
Since pos is greater than buf.len(), the iterator should terminate immediately.
Actual behavior
thread 'main' panicked at /Rust-Lib-Testing/test/tests/crates/quick-xml-0.41.0/src/events/attributes.rs:1224:49:
range start index 2 out of range for slice of length 1
stack backtrace:
0: 0x55fe02a6e428 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h0f9d2e8e73f1bc7d
1: 0x55fe02aad033 - core::fmt::write::h2b15537d64ec9505
2: 0x55fe02a99f5f - std::io::Write::write_fmt::h7f766131a16fe05a
3: 0x55fe02a6e273 - std::sys::backtrace::BacktraceLock::print::h5e38585c963961db
4: 0x55fe02a73f7c - std::panicking::default_hook::{{closure}}::h7a475a2b7b7e4121
5: 0x55fe02a73e1d - std::panicking::default_hook::hac0f4b95d0cecbc2
6: 0x55fe02a74451 - std::panicking::rust_panic_with_hook::hb51ba0f67890aa28
7: 0x55fe02a6e80a - std::panicking::begin_panic_handler::{{closure}}::h73d0277a9a02463b
8: 0x55fe02a6e649 - std::sys::backtrace::__rust_end_short_backtrace::hf93dae6c307b4fe8
9: 0x55fe02a7406d - __rustc[b6f6af4e11d2f413]::rust_begin_unwind
10: 0x55fe02aac0a0 - core::panicking::panic_fmt::h3075732948299e49
11: 0x55fe02aaa597 - core::slice::index::slice_start_index_len_fail::do_panic::runtime::hcc2a5aadc9262237
12: 0x55fe02aaa4ca - core::slice::index::slice_start_index_len_fail::hc732b73cbbe828f6
13: 0x55fe02a6accd - <core::ops::range::RangeFrom<usize> as core::slice::index::SliceIndex<[T]>>::index::he33b10440abe67b2
at /Rust-Lib-Testing/test/src/rust/library/core/src/slice/index.rs:570:13
14: 0x55fe02a5ffa7 - core::slice::index::<impl core::ops::index::Index<I> for [T]>::index::h737ba69d80e4a2ac
at /Rust-Lib-Testing/test/src/rust/library/core/src/slice/index.rs:18:15
15: 0x55fe02a5ffa7 - quick_xml::events::attributes::IterState::next::h1cab26926d07055b
at /Rust-Lib-Testing/test/tests/crates/quick-xml-0.41.0/src/events/attributes.rs:1224:49
16: 0x55fe02a5efb0 - <quick_xml::events::attributes::Attributes as core::iter::traits::iterator::Iterator>::next::h19869966ebbf405f
at /Rust-Lib-Testing/test/tests/crates/quick-xml-0.41.0/src/events/attributes.rs:698:26
17: 0x55fe02a63440 - core::iter::traits::iterator::Iterator::try_fold::hf926e2a9c4d7363f
at /Rust-Lib-Testing/test/src/rust/library/core/src/iter/traits/iterator.rs:2425:34
18: 0x55fe02a633e4 - core::iter::traits::iterator::Iterator::any::h46c8a83f373b4437
at /Rust-Lib-Testing/test/src/rust/library/core/src/iter/traits/iterator.rs:2826:14
19: 0x55fe02a5ef74 - quick_xml::events::attributes::Attributes::has_nil::h129362b91d57b1f7
at /Rust-Lib-Testing/test/tests/crates/quick-xml-0.41.0/src/events/attributes.rs:651:14
20: 0x55fe02a56b5d - replay_quick_xml1::main::h26e7f01651a50c7a
at /Rust-Lib-Testing/replay_files/quick-xml-0.41.0/replay_quick-xml1/src/main.rs:7:19
21: 0x55fe02a56d0b - core::ops::function::FnOnce::call_once::h76f46a5897c6fb29
at /Rust-Lib-Testing/test/src/rust/library/core/src/ops/function.rs:253:5
22: 0x55fe02a56bce - std::sys::backtrace::__rust_begin_short_backtrace::h65002fbaeac49652
at /Rust-Lib-Testing/test/src/rust/library/std/src/sys/backtrace.rs:158:18
23: 0x55fe02a56c31 - std::rt::lang_start::{{closure}}::h69d435d19a4676c4
at /Rust-Lib-Testing/test/src/rust/library/std/src/rt.rs:206:18
24: 0x55fe02a99155 - std::rt::lang_start_internal::h9de2b5630c7cec4d
25: 0x55fe02a56c17 - std::rt::lang_start::h830c9996d95df1a2
at /Rust-Lib-Testing/test/src/rust/library/std/src/rt.rs:205:5
26: 0x55fe02a56bbe - main
27: 0x7f674eaa6083 - __libc_start_main
at /build/glibc-B3wQXB/glibc-2.31/csu/../csu/libc-start.c:308:16
28: 0x55fe02a569ee - _start
29: 0x0 - <unknown>
Root cause:
The panic appears to happen in src/events/attributes.rs:
Some(offset) => (offset..).zip(slice[offset..].iter()),
recover(slice) can return Some(offset) where offset > slice.len(). The code then indexes slice[offset..] without checking the bound first.
Description:
quick_xml::events::attributes::Attributes::new(buf, pos)documents that ifposis greater than the buffer length, the iterator should immediately returnNone. However, when such anAttributesiterator is consumed, either directly vianext()or indirectly viahas_nil(), it panics due to an out-of-bounds slice access.Environment:
quick-xml version: 0.41.0
rustc version: 1.94.1
OS: Ubuntu 20.04.6 LTS
Command: RUST_BACKTRACE=full cargo run
PoC
Expected behavior:
Since
posis greater thanbuf.len(), the iterator should terminate immediately.Actual behavior
Root cause:
The panic appears to happen in
src/events/attributes.rs:recover(slice)can returnSome(offset)whereoffset > slice.len(). The code then indexesslice[offset..]without checking the bound first.