The vulnerability is an unbounded memory allocation in rust-zserio when deserializing data from an untrusted source. The root cause is that the size or length of data structures like strings, byte arrays (blobs), and arrays is read from the data stream and used for memory allocation without proper validation. An attacker can craft a malicious zserio stream with a large length value for a string, blob, or array, causing the deserializer to attempt a huge memory allocation, which can lead to a denial of service (DoS) by exhausting system memory.
The vulnerability manifests in three places:
- String deserialization: The
zserio::ztype::string_decode::read_string function reads the string length and allocates a buffer of that size. The patch adds a check to ensure the claimed length does not exceed the available data in the stream.
- Blob/bytes deserialization: The
zserio::ztype::reader::read_bytes function is responsible for reading byte arrays. The patch ensures that the requested number of bytes is not larger than the available data before allocation.
- Array deserialization: For arrays, the vulnerability was in the code generated by the
zserio-rs-build crate. The decode_field function was generating code that allocated the entire array at once using the untrusted length from the stream (vec![...; length]). The patch modifies the code generator to produce code that uses a safer, push-based deserialization for arrays. It also introduces a new zserio::ztype::array::Array::zserio_read implementation that caps the initial memory reservation to a reasonable chunk size (ARRAY_ALLOC_CHUNK), preventing a single large allocation.
The fix involves consistently checking the claimed data size against the available data in the input stream before performing memory allocations. For arrays, the allocation strategy was changed to be incremental rather than a single large block.