Skip to content

Commit f264511

Browse files
Don't preallocate based on bsatn length prefix (#5343)
# Description of Changes Fixes an OOM kill in the proptest `bsatn_invalid_wont_decode`. `bsatn_invalid_wont_decode` generates arbitrary invalid bytes, proves validation fails, then still calls full AlgebraicValue::decode. For generated array-like types, decode reads a u32 length prefix, and the generic array visitor then reserves that capacity. But because they're random bytes, this could cause a huge initial allocation which could OOM kill the test process. Now the visitor reserves a smaller initial capacity instead of assuming the binary input data is well formed. # API and ABI breaking changes N/A # Expected complexity level and risk 1 # Testing This should fix the flaky `spacetimedb-sats` `Test Suite` failures that occasionally end in a SIGKILL.
1 parent a2ca083 commit f264511

1 file changed

Lines changed: 6 additions & 1 deletion

File tree

crates/sats/src/de.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,12 @@ impl<T, const N: usize> GrowingVec<T> for SmallVec<[T; N]> {
771771

772772
/// A basic implementation of `ArrayVisitor::visit` using the provided size hint.
773773
pub fn array_visit<'de, A: ArrayAccess<'de>, V: GrowingVec<A::Element>>(mut access: A) -> Result<V, A::Error> {
774-
let mut v = V::try_with_capacity(access.size_hint().unwrap_or(0))?;
774+
// Don’t blindly trust length prefixes when reserving initial capacity
775+
// for decoding array elements, as malformed input could generate a huge allocation,
776+
// potentially resulting in an OOM kill.
777+
const RESERVE_ARRAY_ELEMENTS: usize = 4096;
778+
let cap = access.size_hint().unwrap_or(0);
779+
let mut v = V::try_with_capacity(cap.min(RESERVE_ARRAY_ELEMENTS))?;
775780
while let Some(x) = access.next_element()? {
776781
v.push(x)
777782
}

0 commit comments

Comments
 (0)