1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-03 10:14:06 +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:13:12 +01:00
commit 3caadadb3b
7 changed files with 14 additions and 7 deletions

View file

@ -2,6 +2,7 @@ use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
use crate::demo::message::stringtable::log_base2; use crate::demo::message::stringtable::log_base2;
use crate::{ReadResult, Stream}; use crate::{ReadResult, Stream};
use std::cmp::min;
#[derive(BitReadSized, Debug)] #[derive(BitReadSized, Debug)]
pub struct ClassInfoEntry { pub struct ClassInfoEntry {
@ -23,7 +24,7 @@ impl BitRead<LittleEndian> for ClassInfoMessage {
let count: u16 = stream.read()?; let count: u16 = stream.read()?;
let create: bool = stream.read()?; let create: bool = stream.read()?;
let entries = if !create { let entries = if !create {
let mut entries = Vec::with_capacity(count as usize); let mut entries = Vec::with_capacity(min(count, 128) as usize);
let bits = log_base2(count); let bits = log_base2(count);
for _ in 0..count { for _ in 0..count {
entries.push(stream.read_sized(bits as usize)?); entries.push(stream.read_sized(bits as usize)?);

View file

@ -8,6 +8,7 @@ use crate::demo::parser::ParseBitSkip;
use crate::demo::sendprop::{SendProp, SendPropDefinition, SendPropValue}; use crate::demo::sendprop::{SendProp, SendPropDefinition, SendPropValue};
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream}; use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use std::cmp::min;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::hint::unreachable_unchecked; use std::hint::unreachable_unchecked;
@ -146,7 +147,7 @@ impl Parse for PacketEntitiesMessage {
let updated_base_line = stream.read()?; let updated_base_line = stream.read()?;
let mut data = stream.read_bits(length as usize)?; let mut data = stream.read_bits(length as usize)?;
let mut entities = Vec::with_capacity(updated_entries as usize); let mut entities = Vec::with_capacity(min(updated_entries, 128) as usize);
let mut removed_entities = Vec::new(); let mut removed_entities = Vec::new();
let mut last_index: i32 = -1; let mut last_index: i32 = -1;

View file

@ -2,6 +2,7 @@ use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
use crate::demo::message::stringtable::log_base2; use crate::demo::message::stringtable::log_base2;
use crate::{ReadResult, Stream}; use crate::{ReadResult, Stream};
use std::cmp::min;
#[derive(Debug)] #[derive(Debug)]
pub struct SetConVarMessage { pub struct SetConVarMessage {
@ -11,7 +12,7 @@ pub struct SetConVarMessage {
impl BitRead<LittleEndian> for SetConVarMessage { impl BitRead<LittleEndian> for SetConVarMessage {
fn read(stream: &mut Stream) -> ReadResult<Self> { fn read(stream: &mut Stream) -> ReadResult<Self> {
let count: u8 = stream.read()?; let count: u8 = stream.read()?;
let mut vars: Vec<(String, String)> = Vec::with_capacity(count as usize); let mut vars: Vec<(String, String)> = Vec::with_capacity(min(count, 128) as usize);
for _ in 0..count { for _ in 0..count {
let key = stream let key = stream
.read() .read()

View file

@ -7,6 +7,7 @@ use crate::demo::packet::stringtable::{
}; };
use crate::demo::parser::ParseBitSkip; use crate::demo::parser::ParseBitSkip;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream}; use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use std::cmp::min;
#[derive(Debug)] #[derive(Debug)]
pub struct CreateStringTableMessage { pub struct CreateStringTableMessage {
@ -149,7 +150,7 @@ struct TableEntries {
impl TableEntries { impl TableEntries {
pub fn new(count: usize) -> Self { pub fn new(count: usize) -> Self {
TableEntries { TableEntries {
entries: Vec::with_capacity(count), entries: Vec::with_capacity(min(count, 128)),
history: Vec::with_capacity(32), history: Vec::with_capacity(32),
} }
} }

View file

@ -9,6 +9,7 @@ use parse_display::{Display, FromStr};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::borrow::Borrow; use std::borrow::Borrow;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::cmp::min;
use std::fmt; use std::fmt;
use std::num::ParseIntError; use std::num::ParseIntError;
use std::ops::Deref; use std::ops::Deref;
@ -83,7 +84,7 @@ impl ParseSendTable {
let prop_count = stream.read_int(10)?; let prop_count = stream.read_int(10)?;
let mut array_element_prop = None; let mut array_element_prop = None;
let mut props = Vec::with_capacity(prop_count); let mut props = Vec::with_capacity(min(prop_count, 128));
for prop_index in 0..prop_count { for prop_index in 0..prop_count {
let definition_index = SendPropDefinitionIndex::new(table_index, prop_index); let definition_index = SendPropDefinitionIndex::new(table_index, prop_index);

View file

@ -4,6 +4,7 @@ use bitstream_reader::{BitRead, LittleEndian};
use crate::demo::message::stringtable::StringTableMeta; use crate::demo::message::stringtable::StringTableMeta;
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream}; use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
use std::cmp::min;
#[derive(BitRead, Clone, Copy, Debug)] #[derive(BitRead, Clone, Copy, Debug)]
pub struct FixedUserDataSize { pub struct FixedUserDataSize {
@ -36,7 +37,7 @@ impl BitRead<LittleEndian> for StringTable {
fn read(stream: &mut Stream) -> ReadResult<Self> { fn read(stream: &mut Stream) -> ReadResult<Self> {
let name = stream.read()?; let name = stream.read()?;
let entry_count = stream.read_int(16)?; let entry_count = stream.read_int(16)?;
let mut entries = Vec::with_capacity(entry_count as usize); let mut entries = Vec::with_capacity(min(entry_count, 128) as usize);
for index in 0..entry_count { for index in 0..entry_count {
entries.push((index, stream.read()?)) entries.push((index, stream.read()?))

View file

@ -11,6 +11,7 @@ use crate::demo::packet::datatable::SendTableName;
use crate::demo::parser::MalformedSendPropDefinitionError; use crate::demo::parser::MalformedSendPropDefinitionError;
use parse_display::Display; use parse_display::Display;
use serde::export::TryFrom; use serde::export::TryFrom;
use std::cmp::min;
use std::convert::TryInto; use std::convert::TryInto;
use std::fmt; use std::fmt;
use std::rc::Rc; use std::rc::Rc;
@ -423,7 +424,7 @@ impl SendPropValue {
) + 1; ) + 1;
let count = stream.read_int(num_bits as usize)?; let count = stream.read_int(num_bits as usize)?;
let mut values = Vec::with_capacity(count); let mut values = Vec::with_capacity(min(count, 128));
let child_definition = definition let child_definition = definition
.array_property .array_property