From 497543a126e2541b9931e2df1887ea7a51ab9c3c Mon Sep 17 00:00:00 2001 From: Onyeka Obi Date: Thu, 2 Apr 2026 04:19:37 -0700 Subject: [PATCH] Prevent OOM panic in Deserializable::read_batch_from Replace Vec::with_capacity(num_elements) with try_reserve, returning a new TooManyElements error variant instead of panicking when a malicious input claims an absurd element count. Closes #377 --- utils/core/src/errors.rs | 5 +++++ utils/core/src/serde/mod.rs | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/utils/core/src/errors.rs b/utils/core/src/errors.rs index 029c2c859..294131d1f 100644 --- a/utils/core/src/errors.rs +++ b/utils/core/src/errors.rs @@ -18,6 +18,8 @@ pub enum DeserializationError { UnexpectedEOF, /// Deserialization has finished but not all bytes have been consumed. UnconsumedBytes, + /// The requested number of elements could not be allocated. + TooManyElements(usize), /// An unknown error has occurred. UnknownError(String), } @@ -35,6 +37,9 @@ impl fmt::Display for DeserializationError { Self::UnconsumedBytes => { write!(f, "not all bytes were consumed") } + Self::TooManyElements(num) => { + write!(f, "could not allocate memory for {num} elements") + } Self::UnknownError(err_msg) => { write!(f, "unknown error: {err_msg}") } diff --git a/utils/core/src/serde/mod.rs b/utils/core/src/serde/mod.rs index ac912709a..fdc895b5c 100644 --- a/utils/core/src/serde/mod.rs +++ b/utils/core/src/serde/mod.rs @@ -141,7 +141,10 @@ pub trait Deserializable: Sized { source: &mut R, num_elements: usize, ) -> Result, DeserializationError> { - let mut result = Vec::with_capacity(num_elements); + let mut result = Vec::new(); + result + .try_reserve(num_elements) + .map_err(|_| DeserializationError::TooManyElements(num_elements))?; for _ in 0..num_elements { let element = Self::read_from(source)?; result.push(element)