diff --git a/src/reskit/soundtrack/formats/dmf.rs b/src/reskit/soundtrack/formats/dmf.rs index 21f3712..7ceef64 100644 --- a/src/reskit/soundtrack/formats/dmf.rs +++ b/src/reskit/soundtrack/formats/dmf.rs @@ -1,7 +1,7 @@ use std::{error::Error, fs::File, io::Read, convert::TryInto, collections::HashMap}; use flate2::read::ZlibDecoder; use linked_hash_set::LinkedHashSet; -use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, print_info}, soundtrack::types::{SampleFormat, PsgEnvelope, Note, Sample, PsgSettings, PatternRow, Effect, DcsgChannelMode, NoiseType, Instrument, InstrumentType, Fm2612Operator, Fm2612Settings, Channel, CombinedAssets}}; +use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, print_info, sanitize_string}, soundtrack::types::{SampleFormat, PsgEnvelope, Note, Sample, PsgSettings, PatternRow, Effect, DcsgChannelMode, NoiseType, Instrument, InstrumentType, Fm2612Operator, Fm2612Settings, Channel, CombinedAssets}}; const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask."; const DMF_SUPPORTED_VERSION: u8 = 27; @@ -101,10 +101,10 @@ impl DmfModule { }; let song_name_len = get_u8( bytes.by_ref() )?; - print_info( &format!( "Song name:\t{}", get_string( bytes.by_ref(), song_name_len.into() )? ) ); + print_info( &format!( "Song name:\t{}", sanitize_string( get_string( bytes.by_ref(), song_name_len.into() )? ) ) ); let song_author_len = get_u8( bytes.by_ref() )?; - print_info( &format!( "Song author:\t{}", get_string( bytes.by_ref(), song_author_len.into() )? ) ); + print_info( &format!( "Song author:\t{}", sanitize_string( get_string( bytes.by_ref(), song_author_len.into() )? ) ) ); // Burn 2 bytes, don't care about the highlight patterns skip( bytes.by_ref(), 2 ); @@ -182,7 +182,7 @@ impl DmfModule { for i in 0..instrument_count { let name_len = get_u8( bytes.by_ref() )?; - let name = get_string( bytes.by_ref(), name_len.into() )?; + let name = sanitize_string( get_string( bytes.by_ref(), name_len.into() )? ); print_info( &format!( "Instrument {}:\t{}", i, name ) ); @@ -654,7 +654,7 @@ impl DmfModule { for i in 0..num_samples { let sample_size = get_u32( bytes.by_ref() )?; let sample_name_chars = get_u8( bytes.by_ref() )?; - let name = get_string( bytes.by_ref(), sample_name_chars.into() )?; + let name = sanitize_string( get_string( bytes.by_ref(), sample_name_chars.into() )? ); let rate = match get_u8( bytes.by_ref() )? { 1 => 8000, 2 => 11025, diff --git a/src/reskit/utility.rs b/src/reskit/utility.rs index 12eccf3..f496891 100644 --- a/src/reskit/utility.rs +++ b/src/reskit/utility.rs @@ -39,6 +39,15 @@ impl< Type: Copy > Iterator for Ring< Type > { } +/** + * Protect against directory traversal attacks when using identifiers inside of files + */ +pub fn sanitize_string( string: String ) -> String { + string + .replace( "../", "_" ) + .replace( "..\\", "_" ) +} + pub fn symbol_to_pascal( filename: &str ) -> String { filename .replace( "/", "_" )