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:
parent
42c0eb2c89
commit
3caadadb3b
7 changed files with 14 additions and 7 deletions
|
|
@ -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)?);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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()?))
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue