1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-03 10:14:06 +02:00

add some sanity checks to compressed and decompressed size for snap encoded string tables

This commit is contained in:
Robin Appelman 2021-05-23 14:09:28 +02:00
commit bb79d269d8

View file

@ -1,6 +1,6 @@
use bitbuffer::{BitReadBuffer, BitReadStream, LittleEndian}; use bitbuffer::{BitReadBuffer, BitReadStream, LittleEndian};
use num_traits::{PrimInt, Unsigned}; use num_traits::{PrimInt, Unsigned};
use snap::raw::Decoder; use snap::raw::{decompress_len, Decoder};
use crate::demo::packet::stringtable::{ use crate::demo::packet::stringtable::{
ExtraData, FixedUserDataSize, StringTable, StringTableEntry, ExtraData, FixedUserDataSize, StringTable, StringTableEntry,
@ -48,12 +48,18 @@ impl<'a> Parse<'a> for CreateStringTableMessage<'a> {
let decompressed_size: u32 = table_data.read()?; let decompressed_size: u32 = table_data.read()?;
let compressed_size: u32 = table_data.read()?; let compressed_size: u32 = table_data.read()?;
if compressed_size < 4 { if compressed_size < 4 || compressed_size > 10 * 1024 * 1024 {
return Err(ParseError::InvalidDemo( return Err(ParseError::InvalidDemo(
"Invalid compressed string table size", "Invalid compressed string table size",
)); ));
} }
if decompressed_size > 100 * 1024 * 1024 {
return Err(ParseError::InvalidDemo(
"Invalid decompressed string table size",
));
}
let magic = table_data.read_string(Some(4))?; let magic = table_data.read_string(Some(4))?;
if magic != "SNAP" { if magic != "SNAP" {
@ -63,17 +69,21 @@ impl<'a> Parse<'a> for CreateStringTableMessage<'a> {
let compressed_data = table_data.read_bytes(compressed_size as usize - 4)?; let compressed_data = table_data.read_bytes(compressed_size as usize - 4)?;
let mut decoder = Decoder::new(); let mut decoder = Decoder::new();
let decompressed_data = decoder
.decompress_vec(&compressed_data)
.map_err(ParseError::from)?;
if decompressed_data.len() != decompressed_size as usize { let decompressed_size_from_header = decompress_len(&compressed_data)?;
if decompressed_size_from_header != decompressed_size as usize {
return Err(ParseError::UnexpectedDecompressedSize { return Err(ParseError::UnexpectedDecompressedSize {
expected: decompressed_size, expected: decompressed_size,
size: decompressed_data.len() as u32, size: decompressed_size_from_header as u32,
}); });
} }
let mut decompressed_data = vec![0; decompressed_size_from_header];
decoder
.decompress(&compressed_data, &mut decompressed_data)
.map_err(ParseError::from)?;
let buffer = BitReadBuffer::new_owned(decompressed_data, LittleEndian); let buffer = BitReadBuffer::new_owned(decompressed_data, LittleEndian);
table_data = BitReadStream::new(buffer); table_data = BitReadStream::new(buffer);
} }