Skip to content

Avoid potential panic in read_many deserialization #377

@PhilippGackstatter

Description

@PhilippGackstatter

Right now, the ByteReader::read_many function looks like this:

fn read_many<D>(&mut self, num_elements: usize) -> Result<Vec<D>, DeserializationError>
where
Self: Sized,
D: Deserializable,
{
let mut result = Vec::with_capacity(num_elements);
for _ in 0..num_elements {
let element = D::read_from(self)?;
result.push(element)
}
Ok(result)

If num_elements exceeds the system's available memory capacity, Vec::with_capacity panics. Deserialization input can generally not be trusted, and in theory it would be the responsibility of the caller of read_many to validate num_elements or impose limits. However, that is generally not done and is likely to be forgotten, at least in some places. So if a malicious input sets the value of num_elements that is passed to a number that exceeds the available capacity, the attacker can provoke a panic. It would probably be best if we removed the potential for a panic and errored instead if the capacity is too large, e.g.:

let mut result = Vec::new();
result
    .try_reserve(num_elements)
    .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;

(Note that Vec::try_with_capacity exists, but is not stable at this time).

Alternatively, I'd prefer adding a new error variant to DeserializationError directly for this case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions