From ba61ed6ef3e46b06764db7179efece1502d895eb Mon Sep 17 00:00:00 2001 From: Ming Date: Tue, 16 Dec 2025 16:50:41 -0500 Subject: [PATCH] fix: vint buffer can overflow (#2778) * fix vint overflow * comment --- src/postings/compression/mod.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/postings/compression/mod.rs b/src/postings/compression/mod.rs index 487da620c..6b7b0de9f 100644 --- a/src/postings/compression/mod.rs +++ b/src/postings/compression/mod.rs @@ -1,8 +1,10 @@ use bitpacking::{BitPacker, BitPacker4x}; -use common::FixedSize; pub const COMPRESSION_BLOCK_SIZE: usize = BitPacker4x::BLOCK_LEN; -const COMPRESSED_BLOCK_MAX_SIZE: usize = COMPRESSION_BLOCK_SIZE * u32::SIZE_IN_BYTES; +// in vint encoding, each byte stores 7 bits of data, so we need at most 32 / 7 = 4.57 bytes to +// store a u32 in the worst case, rounding up to 5 bytes total +const MAX_VINT_SIZE: usize = 5; +const COMPRESSED_BLOCK_MAX_SIZE: usize = COMPRESSION_BLOCK_SIZE * MAX_VINT_SIZE; mod vint; @@ -267,7 +269,6 @@ impl VIntDecoder for BlockDecoder { #[cfg(test)] pub(crate) mod tests { - use super::*; use crate::TERMINATED; @@ -372,6 +373,13 @@ pub(crate) mod tests { } } } + + #[test] + fn test_compress_vint_unsorted_does_not_overflow() { + let mut encoder = BlockEncoder::new(); + let input: Vec = vec![u32::MAX; COMPRESSION_BLOCK_SIZE]; + encoder.compress_vint_unsorted(&input); + } } #[cfg(all(test, feature = "unstable"))]