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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions