1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-04 00:54:07 +02:00

harden against dos with crafted input by limiting reserved vec/map size

This commit is contained in:
Robin Appelman 2020-01-19 22:09:57 +01:00
commit 894c8aef7c

View file

@ -1,6 +1,7 @@
use crate::endianness::{BigEndian, LittleEndian}; use crate::endianness::{BigEndian, LittleEndian};
use crate::{BitStream, Endianness, Result}; use crate::{BitStream, Endianness, Result};
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp::min;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -507,7 +508,7 @@ impl<E: Endianness> BitReadSized<E> for BitStream<E> {
/// Read `T` `size` times and return as `Vec<T>` /// Read `T` `size` times and return as `Vec<T>`
impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> { impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> { fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
let mut vec = Vec::with_capacity(size); let mut vec = Vec::with_capacity(min(size, 128));
for _ in 0..size { for _ in 0..size {
vec.push(stream.read()?) vec.push(stream.read()?)
} }
@ -516,7 +517,7 @@ impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
#[inline] #[inline]
unsafe fn read_unchecked(stream: &mut BitStream<E>, size: usize) -> Result<Self> { unsafe fn read_unchecked(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
let mut vec = Vec::with_capacity(size); let mut vec = Vec::with_capacity(min(size, 128));
for _ in 0..size { for _ in 0..size {
vec.push(stream.read_unchecked()?) vec.push(stream.read_unchecked()?)
} }
@ -540,7 +541,7 @@ impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
/// Read `K` and `T` `size` times and return as `HashMap<K, T>` /// Read `K` and `T` `size` times and return as `HashMap<K, T>`
impl<E: Endianness, K: BitRead<E> + Eq + Hash, T: BitRead<E>> BitReadSized<E> for HashMap<K, T> { impl<E: Endianness, K: BitRead<E> + Eq + Hash, T: BitRead<E>> BitReadSized<E> for HashMap<K, T> {
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> { fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
let mut map = HashMap::with_capacity(size); let mut map = HashMap::with_capacity(min(size, 128));
for _ in 0..size { for _ in 0..size {
let key = stream.read()?; let key = stream.read()?;
let value = stream.read()?; let value = stream.read()?;
@ -551,7 +552,7 @@ impl<E: Endianness, K: BitRead<E> + Eq + Hash, T: BitRead<E>> BitReadSized<E> fo
#[inline] #[inline]
unsafe fn read_unchecked(stream: &mut BitStream<E>, size: usize) -> Result<Self> { unsafe fn read_unchecked(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
let mut map = HashMap::with_capacity(size); let mut map = HashMap::with_capacity(min(size, 128));
for _ in 0..size { for _ in 0..size {
let key = stream.read_unchecked()?; let key = stream.read_unchecked()?;
let value = stream.read_unchecked()?; let value = stream.read_unchecked()?;