Skip to content

Commit 92dbdf2

Browse files
Merge pull request #70 from triblespace/codex/update-bitvectordata-from_bytes-validation
Validate bit vector metadata length
2 parents 8a351c9 + bdcbbb1 commit 92dbdf2

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Changelog
22

33
## Unreleased
4+
- Added metadata validation in `BitVectorData::from_bytes` to reject lengths
5+
exceeding the stored capacity and covered the case with a regression test.
46
- Guarded `CompactVector::from_bytes` against metadata bit-length overflow.
57
- Removed the `anyhow` dependency in favor of crate-defined errors and updated
68
`Serializable` to expose an associated error type for reconstruction.

src/bit_vector/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,17 @@ impl BitVectorData {
388388
/// Reconstructs the data from zero-copy [`Bytes`] and its metadata.
389389
pub fn from_bytes(meta: BitVectorDataMeta, bytes: Bytes) -> Result<Self> {
390390
let words = meta.handle.view(&bytes)?;
391+
let capacity_bits = words
392+
.as_ref()
393+
.len()
394+
.checked_mul(WORD_LEN)
395+
.ok_or_else(|| Error::invalid_metadata("bit vector capacity overflow"))?;
396+
if meta.len > capacity_bits {
397+
return Err(Error::invalid_metadata(format!(
398+
"bit vector length {} exceeds capacity {}",
399+
meta.len, capacity_bits
400+
)));
401+
}
391402
Ok(Self {
392403
words,
393404
len: meta.len,
@@ -760,6 +771,23 @@ mod tests {
760771
assert_eq!(expected, other);
761772
}
762773

774+
#[test]
775+
fn from_bytes_rejects_metadata_len_overflow() {
776+
let mut area = ByteArea::new().unwrap();
777+
let mut sections = area.sections();
778+
let builder = BitVectorBuilder::with_capacity(WORD_LEN, &mut sections).unwrap();
779+
let data = builder.into_data();
780+
let mut meta = data.metadata();
781+
let capacity_bits = data.num_words() * WORD_LEN;
782+
meta.len = capacity_bits + 1;
783+
drop(data);
784+
drop(sections);
785+
let bytes = area.freeze().unwrap();
786+
787+
let err = BitVectorData::from_bytes(meta, bytes).unwrap_err();
788+
assert!(matches!(err, Error::InvalidMetadata(_)));
789+
}
790+
763791
#[test]
764792
fn get_bits_wrapper() {
765793
let data = BitVectorData::from_bits([true, false, true, true, false]);

0 commit comments

Comments
 (0)