1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-04 02:24:12 +02:00

remove some bounds checks

This commit is contained in:
Robin Appelman 2025-07-14 14:52:38 +02:00
commit 6ef2b1cea8
9 changed files with 102 additions and 93 deletions

View file

@ -1,6 +1,7 @@
use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
use parse_display::Display;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use crate::demo::gameevent_gen::GameEventType;
use crate::demo::gamevent::{
@ -75,18 +76,15 @@ fn test_game_event_roundtrip() {
GameEventDefinition {
id: GameEventTypeId(0),
event_type: GameEventType::ServerShutdown,
entries: vec![GameEventEntry {
name: "reason".to_string(),
kind: GameEventValueType::String,
}],
entries: vec![GameEventEntry::new("reason", GameEventValueType::String)],
},
GameEventDefinition {
id: GameEventTypeId(1),
event_type: GameEventType::ServerChangeLevelFailed,
entries: vec![GameEventEntry {
name: "level_name".to_string(),
kind: GameEventValueType::String,
}],
entries: vec![GameEventEntry::new(
"level_name",
GameEventValueType::String,
)],
},
GameEventDefinition {
id: GameEventTypeId(2),
@ -168,11 +166,8 @@ impl BitRead<'_, LittleEndian> for GameEventDefinition {
let mut entry_type = stream.read()?;
while entry_type != GameEventValueType::None {
let entry_name = stream.read()?;
entries.push(GameEventEntry {
name: entry_name,
kind: entry_type,
});
let entry_name: Cow<str> = stream.read()?;
entries.push(GameEventEntry::new(entry_name, entry_type));
entry_type = stream.read()?;
}
@ -207,10 +202,10 @@ fn test_event_definition_roundtrip() {
crate::test_roundtrip_write(GameEventDefinition {
id: GameEventTypeId(0),
event_type: GameEventType::ServerChangeLevelFailed,
entries: vec![GameEventEntry {
name: "level_name".to_string(),
kind: GameEventValueType::String,
}],
entries: vec![GameEventEntry::new(
"level_name",
GameEventValueType::String,
)],
});
}
@ -244,10 +239,7 @@ fn test_event_list_roundtrip() {
event_list: vec![GameEventDefinition {
id: GameEventTypeId(0),
event_type: GameEventType::ServerChangeLevelFailed,
entries: vec![GameEventEntry {
name: "level_name".to_string(),
kind: GameEventValueType::String,
}],
entries: vec![GameEventEntry::new("level_name", GameEventValueType::String)],
}],
});
crate::test_roundtrip_write(GameEventListMessage {
@ -256,55 +248,25 @@ fn test_event_list_roundtrip() {
id: GameEventTypeId(0),
event_type: GameEventType::ServerSpawn,
entries: vec![
GameEventEntry {
name: "hostname".to_string(),
kind: GameEventValueType::String,
},
GameEventEntry {
name: "address".to_string(),
kind: GameEventValueType::String,
},
GameEventEntry {
name: "ip".to_string(),
kind: GameEventValueType::Long,
},
GameEventEntry {
name: "port".to_string(),
kind: GameEventValueType::Short,
},
GameEventEntry {
name: "game".to_string(),
kind: GameEventValueType::String,
},
GameEventEntry {
name: "map_name".to_string(),
kind: GameEventValueType::String,
},
GameEventEntry {
name: "max_players".to_string(),
kind: GameEventValueType::Long,
},
GameEventEntry {
name: "os".to_string(),
kind: GameEventValueType::String,
},
GameEventEntry {
name: "dedicated".to_string(),
kind: GameEventValueType::Boolean,
},
GameEventEntry {
name: "password".to_string(),
kind: GameEventValueType::Boolean,
},
GameEventEntry::new("hostname", GameEventValueType::String),
GameEventEntry::new("address", GameEventValueType::String),
GameEventEntry::new("ip", GameEventValueType::Long),
GameEventEntry::new("port", GameEventValueType::Short),
GameEventEntry::new("game", GameEventValueType::String),
GameEventEntry::new("map_name", GameEventValueType::String),
GameEventEntry::new("max_players", GameEventValueType::Long),
GameEventEntry::new("os", GameEventValueType::String),
GameEventEntry::new("dedicated", GameEventValueType::Boolean),
GameEventEntry::new("password", GameEventValueType::Boolean),
],
},
GameEventDefinition {
id: GameEventTypeId(1),
event_type: GameEventType::ServerChangeLevelFailed,
entries: vec![GameEventEntry {
name: "level_name".to_string(),
kind: GameEventValueType::String,
}],
entries: vec![GameEventEntry::new(
"level_name",
GameEventValueType::String,
)],
},
GameEventDefinition {
id: GameEventTypeId(2),

View file

@ -6,7 +6,6 @@ use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::borrow::Cow;
use crate::demo::message::stringtable::log_base2;
use crate::demo::packet::datatable::{ClassId, SendTable};
use crate::demo::parser::{Encode, ParseBitSkip};
use crate::demo::sendprop::{SendProp, SendPropIdentifier, SendPropValue};
@ -352,10 +351,21 @@ impl Parse<'_> for PacketEntitiesMessage {
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
let max_entries = stream.read_sized(11)?;
let delta: Option<ServerTick> = stream.read()?;
let base_line = stream.read()?;
let updated_entries: u16 = stream.read_sized(11)?;
let length: u32 = stream.read_sized(20)?;
let updated_base_line = stream.read()?;
#[derive(BitRead)]
struct Header {
base_line: BaselineIndex,
#[bitbuffer(size = 11)]
updated_entries: u16,
#[bitbuffer(size = 20)]
length: u32,
updated_base_line: bool,
}
let Header {
base_line,
updated_entries,
length,
updated_base_line,
} = stream.read()?;
let mut data = stream.read_bits(length as usize)?;
@ -486,10 +496,16 @@ impl PacketEntitiesMessage {
baseline_index: BaselineIndex,
delta: Option<ServerTick>,
) -> Result<PacketEntity> {
let bits = log_base2(state.server_classes.len()) + 1;
let class_index: ClassId = stream.read_sized::<u16>(bits as usize)?.into();
let serial = stream.read_sized(10)?;
let bits = state.server_class_bits;
#[derive(BitReadSized)]
struct Data {
#[bitbuffer(size = "input_size")]
raw_index: u16,
#[bitbuffer(size = 10)]
serial: u32,
}
let Data { raw_index, serial } = stream.read_sized(bits)?;
let class_index: ClassId = raw_index.into();
Ok(PacketEntity {
server_class: class_index,
@ -509,8 +525,7 @@ impl PacketEntitiesMessage {
stream: &mut BitWriteStream<LittleEndian>,
state: &ParserState,
) -> Result<()> {
let bits = log_base2(state.server_classes.len()) + 1;
u16::from(entity.server_class).write_sized(stream, bits as usize)?;
u16::from(entity.server_class).write_sized(stream, state.server_class_bits)?;
entity.serial_number.write_sized(stream, 10)?;
Ok(())
@ -613,12 +628,12 @@ impl ParseBitSkip<'_> for PacketEntitiesMessage {
}
#[test]
fn test_packet_entitier_message_roundtrip() {
fn test_packet_entity_message_roundtrip() {
use crate::demo::packet::datatable::{SendTable, SendTableName, ServerClass, ServerClassName};
use crate::demo::sendprop::{FloatDefinition, SendPropDefinition, SendPropParseDefinition};
let mut state = ParserState::new(24, |_| false, false);
state.server_classes = vec![
state.set_server_classes(vec![
ServerClass {
id: ClassId::from(0),
name: ServerClassName::from("class1"),
@ -629,7 +644,7 @@ fn test_packet_entitier_message_roundtrip() {
name: ServerClassName::from("class2"),
data_table: SendTableName::from("table2"),
},
];
]);
state.send_tables = vec![
SendTable {
name: SendTableName::from("table1"),

View file

@ -1,6 +1,6 @@
use super::stringtable::read_var_int;
use crate::demo::message::packetentities::PacketEntitiesMessage;
use crate::demo::message::stringtable::{encode_var_int_fixed, log_base2};
use crate::demo::message::stringtable::{encode_var_int_fixed};
use crate::demo::packet::datatable::ClassId;
use crate::demo::parser::{Encode, ParseBitSkip};
use crate::demo::sendprop::SendProp;
@ -53,8 +53,8 @@ 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)?.saturating_sub(1)).into()
let bits = state.server_class_bits;
(stream.read_sized::<u16>(bits)?.saturating_sub(1)).into()
} else {
let last = events.last().ok_or(ParseError::InvalidDemo(
"temp entity update without previous",
@ -118,9 +118,9 @@ impl Encode for TempEntitiesMessage {
if event.class_id != last_class_id {
true.write(stream)?;
let bits = log_base2(state.server_classes.len()) + 1;
let bits = state.server_class_bits;
let id: u16 = event.class_id.into();
(id + 1).write_sized(stream, bits as usize)?;
(id + 1).write_sized(stream, bits)?;
} else {
false.write(stream)?;
}