mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
additional hardening against mallformed demos
This commit is contained in:
parent
968cc80bee
commit
a7a46384ce
4 changed files with 45 additions and 9 deletions
|
|
@ -297,6 +297,9 @@ impl Parse<'_> for PacketEntitiesMessage {
|
|||
for _ in 0..updated_entries {
|
||||
let diff: u32 = read_bit_var(&mut data)?;
|
||||
last_index = last_index.saturating_add(diff as i32).saturating_add(1);
|
||||
if last_index >= 2048 {
|
||||
return Err(ParseError::InvalidDemo("invalid entity index"));
|
||||
}
|
||||
let entity_index = EntityId::from(last_index as u32);
|
||||
|
||||
let update_type = data.read()?;
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ pub fn parse_string_table_update<'a>(
|
|||
|
||||
for _ in 0..entry_count {
|
||||
let index = if stream.read()? {
|
||||
(last_entry + 1) as u16
|
||||
last_entry.saturating_add(1) as u16
|
||||
} else {
|
||||
stream.read_sized(entry_bits as usize)?
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ impl Parse<'_> for TempEntitiesMessage {
|
|||
|
||||
let class_id = if stream.read()? {
|
||||
let bits = log_base2(state.server_classes.len()) + 1;
|
||||
(stream.read_sized::<u16>(bits as usize)? - 1).into()
|
||||
(stream.read_sized::<u16>(bits as usize)?.saturating_sub(1)).into()
|
||||
} else {
|
||||
let last = events.last().ok_or(ParseError::InvalidDemo(
|
||||
"temp entity update without previous",
|
||||
|
|
|
|||
|
|
@ -319,7 +319,12 @@ fn test_parse_send_table_roundtrip() {
|
|||
impl ParseSendTable {
|
||||
pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Result<Vec<SendPropDefinition>> {
|
||||
let mut flat = Vec::with_capacity(32);
|
||||
self.get_all_props(tables, &self.get_excludes(tables), &mut flat)?;
|
||||
self.get_all_props(
|
||||
tables,
|
||||
&self.get_excludes(tables, &mut Vec::with_capacity(8)),
|
||||
&mut flat,
|
||||
Vec::with_capacity(8),
|
||||
)?;
|
||||
|
||||
// sort often changed props before the others
|
||||
let mut start = 0;
|
||||
|
|
@ -335,7 +340,12 @@ impl ParseSendTable {
|
|||
Ok(flat)
|
||||
}
|
||||
|
||||
fn get_excludes<'a>(&'a self, tables: &'a [ParseSendTable]) -> Vec<SendPropIdentifier> {
|
||||
fn get_excludes<'a>(
|
||||
&'a self,
|
||||
tables: &'a [ParseSendTable],
|
||||
processed_tables: &mut Vec<SendTableName>,
|
||||
) -> Vec<SendPropIdentifier> {
|
||||
processed_tables.push(self.name.clone());
|
||||
let mut excludes = Vec::with_capacity(8);
|
||||
|
||||
for prop in self.props.iter() {
|
||||
|
|
@ -345,7 +355,9 @@ impl ParseSendTable {
|
|||
prop.name.as_str(),
|
||||
))
|
||||
} else if let Some(table) = prop.get_data_table(tables) {
|
||||
excludes.extend_from_slice(&table.get_excludes(tables));
|
||||
if !processed_tables.contains(&table.name) {
|
||||
excludes.extend_from_slice(&table.get_excludes(tables, processed_tables));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,10 +370,17 @@ impl ParseSendTable {
|
|||
tables: &[ParseSendTable],
|
||||
excludes: &[SendPropIdentifier],
|
||||
props: &mut Vec<SendPropDefinition>,
|
||||
processed_tables: Vec<SendTableName>,
|
||||
) -> Result<()> {
|
||||
let mut local_props = Vec::new();
|
||||
|
||||
self.get_all_props_iterator_props(tables, excludes, &mut local_props, props)?;
|
||||
self.get_all_props_iterator_props(
|
||||
tables,
|
||||
excludes,
|
||||
&mut local_props,
|
||||
props,
|
||||
processed_tables,
|
||||
)?;
|
||||
props.extend_from_slice(&local_props);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -372,17 +391,31 @@ impl ParseSendTable {
|
|||
excludes: &[SendPropIdentifier],
|
||||
local_props: &mut Vec<SendPropDefinition>,
|
||||
props: &mut Vec<SendPropDefinition>,
|
||||
processed_tables: Vec<SendTableName>,
|
||||
) -> Result<()> {
|
||||
let processed_tables = &processed_tables;
|
||||
self.props
|
||||
.iter()
|
||||
.filter(|prop| !prop.is_exclude())
|
||||
.filter(|prop| !excludes.iter().any(|exclude| *exclude == prop.identifier()))
|
||||
.try_for_each(|prop| {
|
||||
let mut child_processed_tables = processed_tables.clone();
|
||||
child_processed_tables.push(self.name.clone());
|
||||
if let Some(table) = prop.get_data_table(tables) {
|
||||
if prop.flags.contains(SendPropFlag::Collapsible) {
|
||||
table.get_all_props_iterator_props(tables, excludes, local_props, props)?;
|
||||
if !processed_tables.contains(&table.name) {
|
||||
if prop.flags.contains(SendPropFlag::Collapsible) {
|
||||
table.get_all_props_iterator_props(
|
||||
tables,
|
||||
excludes,
|
||||
local_props,
|
||||
props,
|
||||
child_processed_tables,
|
||||
)?;
|
||||
} else {
|
||||
table.get_all_props(tables, excludes, props, child_processed_tables)?;
|
||||
}
|
||||
} else {
|
||||
table.get_all_props(tables, excludes, props)?;
|
||||
dbg!(table.name.as_str());
|
||||
}
|
||||
} else {
|
||||
local_props.push(SendPropDefinition::try_from(prop)?);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue