Added a multitude of safety checks to the MIDI file processor

CQTexperiment
Chris Moeller 2013-10-25 14:00:51 -07:00
parent 80fe43cdd7
commit d9971ee32f
10 changed files with 146 additions and 84 deletions

View File

@ -24,8 +24,8 @@ class midi_processor
static const uint8_t lds_default_tempo[5];
static int decode_delta( std::vector<uint8_t>::const_iterator & it );
static unsigned decode_hmp_delta( std::vector<uint8_t>::const_iterator & it );
static int decode_delta( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end );
static unsigned decode_hmp_delta( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end );
static unsigned decode_xmi_delta( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end );
static bool is_standard_midi( std::vector<uint8_t> const& p_file );

View File

@ -4,12 +4,13 @@ const uint8_t midi_processor::end_of_track[2] = {0xFF, 0x2F};
const uint8_t midi_processor::loop_start[11] = {0xFF, 0x06, 'l', 'o', 'o', 'p', 'S', 't', 'a', 'r', 't'};
const uint8_t midi_processor::loop_end[9] = {0xFF, 0x06, 'l', 'o', 'o', 'p', 'E', 'n', 'd'};
int midi_processor::decode_delta( std::vector<uint8_t>::const_iterator & it )
int midi_processor::decode_delta( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end )
{
int delta = 0;
unsigned char byte;
do
{
if ( it == end ) return 0;
byte = *it++;
delta = ( delta << 7 ) + ( byte & 0x7F );
}

View File

@ -18,6 +18,9 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
uint32_t track_count = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
uint32_t track_table_offset = it[ 4 ] | ( it[ 5 ] << 8 ) | ( it[ 6 ] << 16 ) | ( it[ 7 ] << 24 );
if ( track_table_offset >= p_file.size() || track_table_offset + track_count * 4 > p_file.size() )
return false;
it = p_file.begin() + track_table_offset;
std::vector<uint32_t> track_offsets;
@ -50,6 +53,9 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
{
track_length = p_file.size() - track_offset;
}
if ( track_offset >= p_file.size() || track_offset + track_length > p_file.size() )
return false;
std::vector<uint8_t>::const_iterator track_body = p_file.begin() + track_offset;
std::vector<uint8_t>::const_iterator track_end = track_body + track_length;
@ -93,9 +99,9 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
buffer.resize( 3 );
while ( it < track_end )
while ( it != track_end )
{
int delta = decode_delta( it );
int delta = decode_delta( it, track_end );
if ( delta > 0xFFFF || delta < 0 )
{
current_timestamp = last_event_timestamp;
@ -110,13 +116,16 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
}
}
if ( it == track_end ) return false;
buffer[ 0 ] = *it++;
if ( buffer[ 0 ] == 0xFF )
{
last_event_code = 0xFF;
if ( it == track_end ) return false;
buffer[ 1 ] = *it++;
int meta_count = decode_delta( it );
int meta_count = decode_delta( it, track_end );
if ( meta_count < 0 ) return false; /*throw exception_io_data( "Invalid HMI meta message" );*/
if ( track_end - it < meta_count ) return false;
buffer.resize( meta_count + 2 );
std::copy( it, it + meta_count, buffer.begin() + 2 );
it += meta_count;
@ -130,8 +139,9 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
else if ( buffer[ 0 ] == 0xF0 )
{
last_event_code = 0xFF;
int system_exclusive_count = decode_delta( it );
int system_exclusive_count = decode_delta( it, track_end );
if ( system_exclusive_count < 0 ) return false; /*throw exception_io_data( "Invalid HMI System Exclusive message" );*/
if ( track_end - it < system_exclusive_count ) return false;
buffer.resize( system_exclusive_count + 1 );
std::copy( it, it + system_exclusive_count, buffer.begin() + 1 );
it += system_exclusive_count;
@ -140,28 +150,35 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
else if ( buffer[ 0 ] == 0xFE )
{
last_event_code = 0xFF;
if ( it == track_end ) return false;
buffer[ 1 ] = *it++;
if ( buffer[ 1 ] == 0x10 )
{
if ( track_end - it < 3 ) return false;
it += 2;
buffer[ 2 ] = *it++;
if ( track_end - it < buffer[ 2 ] + 4 ) return false;
it += buffer[ 2 ] + 4;
}
else if ( buffer[ 1 ] == 0x12 )
{
if ( track_end - it < 2 ) return false;
it += 2;
}
else if ( buffer[ 1 ] == 0x13 )
{
if ( track_end - it < 10 ) return false;
it += 10;
}
else if ( buffer[ 1 ] == 0x14 )
{
if ( track_end - it < 2 ) return false;
it += 2;
p_out.add_track_event( 0, midi_event( current_timestamp, midi_event::extended, 0, loop_start, _countof( loop_start ) ) );
}
else if ( buffer[ 1 ] == 0x15 )
{
if ( track_end - it < 6 ) return false;
it += 6;
p_out.add_track_event( 0, midi_event( current_timestamp, midi_event::extended, 0, loop_end, _countof( loop_end ) ) );
}
@ -172,6 +189,7 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
unsigned bytes_read = 1;
if ( buffer[ 0 ] >= 0x80 )
{
if ( it == track_end ) return false;
buffer[ 1 ] = *it++;
last_event_code = buffer[ 0 ];
}
@ -185,6 +203,7 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
unsigned channel = buffer[ 0 ] & 0x0F;
if ( type != midi_event::program_change && type != midi_event::channel_aftertouch )
{
if ( it == track_end ) return false;
buffer[ 2 ] = *it++;
bytes_read = 2;
}
@ -192,7 +211,7 @@ bool midi_processor::process_hmi( std::vector<uint8_t> const& p_file, midi_conta
if ( type == midi_event::note_on )
{
buffer[ 2 ] = 0x00;
int note_length = decode_delta( it );
int note_length = decode_delta( it, track_end );
if ( note_length < 0 ) return false; /*throw exception_io_data( "Invalid HMI note message" );*/
unsigned note_end_timestamp = current_timestamp + note_length;
if ( note_end_timestamp > last_event_timestamp ) last_event_timestamp = note_end_timestamp;

View File

@ -11,13 +11,14 @@ bool midi_processor::is_hmp( std::vector<uint8_t> const& p_file )
return true;
}
unsigned midi_processor::decode_hmp_delta( std::vector<uint8_t>::const_iterator & it )
unsigned midi_processor::decode_hmp_delta( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end )
{
unsigned delta = 0;
unsigned shift = 0;
unsigned char byte;
do
{
if ( it == end ) return 0;
byte = *it++;
delta = delta + ( ( byte & 0x7F ) << shift );
shift += 7;
@ -33,12 +34,20 @@ bool midi_processor::process_hmp( std::vector<uint8_t> const& p_file, midi_conta
uint8_t track_count_8;
uint16_t dtx = 0xC0;
std::vector<uint8_t>::const_iterator it = p_file.begin() + ( is_funky ? 0x1A : 0x30 );
uint32_t offset = is_funky ? 0x1A : 0x30;
if ( offset >= p_file.size() )
return false;
std::vector<uint8_t>::const_iterator it = p_file.begin() + offset;
std::vector<uint8_t>::const_iterator end = p_file.end();
track_count_8 = *it;
if ( is_funky )
{
if ( p_file.size() <= 0x4D )
return false;
dtx = ( p_file[ 0x4C ] << 16 ) | p_file[ 0x4D ];
}
@ -53,15 +62,17 @@ bool midi_processor::process_hmp( std::vector<uint8_t> const& p_file, midi_conta
uint8_t buffer[ 4 ];
if ( it == end ) return false;
buffer[ 0 ] = *it++;
while ( it < p_file.end() )
while ( it != end )
{
if ( buffer[ 0 ] != 0xFF )
{
buffer[ 0 ] = *it++;
continue;
}
if ( it == end ) break;
buffer[ 1 ] = *it++;
if ( buffer[ 1 ] != 0x2F )
{
@ -71,7 +82,9 @@ bool midi_processor::process_hmp( std::vector<uint8_t> const& p_file, midi_conta
break;
}
it += ( is_funky ? 3 : 5 );
offset = is_funky ? 3 : 5;
if ( (unsigned long)(end - it) < offset ) return false;
it += offset;
unsigned track_count = track_count_8;
@ -82,18 +95,20 @@ bool midi_processor::process_hmp( std::vector<uint8_t> const& p_file, midi_conta
if ( is_funky )
{
if ( end - it < 4 ) break;
track_size_16 = it[ 0 ] | ( it[ 1 ] << 8 );
it += 2;
track_size_32 = track_size_16 - 4;
if ( p_file.end() - it < track_size_32 + 2 ) break;
if ( (unsigned long)(end - it) < track_size_32 + 2 ) break;
it += 2;
}
else
{
if ( end - it < 8 ) break;
track_size_32 = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
it += 4;
track_size_32 -= 12;
if ( p_file.end() - it < track_size_32 + 8 ) break;
if ( (unsigned long)(end - it) < track_size_32 + 8 ) break;
it += 4;
}
@ -106,16 +121,19 @@ bool midi_processor::process_hmp( std::vector<uint8_t> const& p_file, midi_conta
std::vector<uint8_t>::const_iterator track_end = it + track_size_32;
while ( it < track_end )
while ( it != track_end )
{
unsigned delta = decode_hmp_delta( it );
unsigned delta = decode_hmp_delta( it, track_end );
current_timestamp += delta;
if ( it == track_end ) return false;
buffer[ 0 ] = *it++;
if ( buffer[ 0 ] == 0xFF )
{
if ( it == track_end ) return false;
buffer[ 1 ] = *it++;
int meta_count = decode_delta( it );
int meta_count = decode_delta( it, track_end );
if ( meta_count < 0 ) return false; /*throw exception_io_data( "Invalid HMP meta message" );*/
if ( track_end - it < meta_count ) return false;
buffer.resize( meta_count + 2 );
std::copy( it, it + meta_count, buffer.begin() + 2 );
it += meta_count;
@ -131,6 +149,7 @@ bool midi_processor::process_hmp( std::vector<uint8_t> const& p_file, midi_conta
case 0xD0:
bytes_read = 1;
}
if ( (unsigned long)(track_end - it) < bytes_read ) return false;
std::copy( it, it + bytes_read, buffer.begin() + 1 );
it += bytes_read;
track.add_event( midi_event( current_timestamp, (midi_event::event_type)( ( buffer[ 0 ] >> 4 ) - 8 ), buffer[ 0 ] & 0x0F, &buffer[1], bytes_read ) );
@ -138,7 +157,9 @@ bool midi_processor::process_hmp( std::vector<uint8_t> const& p_file, midi_conta
else return false; /*throw exception_io_data( "Unexpected status code in HMP track" );*/
}
it = track_end + ( is_funky ? 0 : 4 );
offset = is_funky ? 0 : 4;
if ( end - it < (signed long)offset ) return false;
it = track_end + offset;
p_out.add_track( track );
}

View File

@ -334,20 +334,26 @@ bool midi_processor::process_lds( std::vector<uint8_t> const& p_file, midi_conta
std::vector<uint16_t> patterns;
std::vector<uint8_t>::const_iterator it = p_file.begin();
std::vector<uint8_t>::const_iterator end = p_file.end();
if ( end == it ) return false;
mode = *it++;
if ( mode > 2 ) return false; /*throw exception_io_data( "Invalid LDS mode" );*/
/*speed = it[ 0 ] | ( it[ 1 ] << 8 );*/
if ( end - it < 4 ) return false;
tempo = it[ 2 ];
pattern_length = it[ 3 ];
it += 4;
if ( end - it < 9 ) return false;
for ( unsigned i = 0; i < 9; ++i )
channel_delay[ i ] = *it++;
/*register_bd = *it++;*/ it++;
if ( end - it < 2 ) return false;
patch_count = it[ 0 ] | ( it[ 1 ] << 8 );
it += 2;
patches.resize( patch_count );
if ( end - it < 46 * patch_count ) return false;
for ( unsigned i = 0; i < patch_count; ++i )
{
sound_patch & patch = patches[ i ];
@ -396,9 +402,11 @@ bool midi_processor::process_lds( std::vector<uint8_t> const& p_file, midi_conta
#endif
}
if ( end - it < 2 ) return false;
position_count = it[ 0 ] | ( it[ 1 ] << 8 );
it += 2;
positions.resize( 9 * position_count );
if ( end - it < 3 * position_count ) return false;
for ( unsigned i = 0; i < position_count; ++i )
{
for ( unsigned j = 0; j < 9; ++j )
@ -412,9 +420,10 @@ bool midi_processor::process_lds( std::vector<uint8_t> const& p_file, midi_conta
}
}
if ( end - it < 2 ) return false;
it += 2;
pattern_count = ( p_file.end() - it ) / 2;
pattern_count = ( end - it ) / 2;
patterns.resize( pattern_count );
for ( unsigned i = 0; i < pattern_count; ++i )
{
@ -550,7 +559,7 @@ bool midi_processor::process_lds( std::vector<uint8_t> const& p_file, midi_conta
}
}
}
else if(((allvolume + (0x100 - fadeonoff)) & 0xff) <= mainvolume)
else if((unsigned)((allvolume + (0x100 - fadeonoff)) & 0xff) <= mainvolume)
{
allvolume += 0x100 - fadeonoff;
}
@ -596,7 +605,7 @@ bool midi_processor::process_lds( std::vector<uint8_t> const& p_file, midi_conta
unsigned short patnum = positions[posplay * 9 + chan].pattern_number;
unsigned char transpose = positions[posplay * 9 + chan].transpose;
if ( patnum + c->packpos >= patterns.size() ) return false; /*throw exception_io_data( "Invalid LDS pattern number" );*/
if ( (unsigned long)(patnum + c->packpos) >= patterns.size() ) return false; /*throw exception_io_data( "Invalid LDS pattern number" );*/
unsigned comword = patterns[patnum + c->packpos];
unsigned comhi = comword >> 8;

View File

@ -13,10 +13,13 @@ bool midi_processor::is_mids( std::vector<uint8_t> const& p_file )
bool midi_processor::process_mids( std::vector<uint8_t> const& p_file, midi_container & p_out )
{
if ( p_file.size() < 20 ) return false;
std::vector<uint8_t>::const_iterator it = p_file.begin() + 16;
std::vector<uint8_t>::const_iterator end = p_file.end();
uint32_t fmt_size = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
it += 4;
if ( (unsigned long)(end - it) < fmt_size ) return false;
uint32_t time_format = 1;
/*uint32_t max_buffer = 0;*/
@ -42,10 +45,12 @@ bool midi_processor::process_mids( std::vector<uint8_t> const& p_file, midi_cont
}
it += fmt_size;
if ( it == end ) return false;
if ( fmt_size & 1 ) ++it;
p_out.initialize( 0, time_format );
if ( end - it < 4 ) return false;
if ( it[ 0 ] != 'd' || it[ 1 ] != 'a' || it[ 2 ] != 't' || it[ 3 ] != 'a' ) return false; /*throw exception_io_data( "MIDS missing RIFF data chunk" );*/
it += 4;
@ -56,11 +61,13 @@ bool midi_processor::process_mids( std::vector<uint8_t> const& p_file, midi_cont
p_out.add_track( track );
}
if ( end - it < 4 ) return false;
uint32_t data_size = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
it += 4;
std::vector<uint8_t>::const_iterator body_end = it + data_size;
if ( body_end - it < 4 ) return false;
uint32_t segment_count = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
it += 4;
@ -72,17 +79,24 @@ bool midi_processor::process_mids( std::vector<uint8_t> const& p_file, midi_cont
for ( unsigned i = 0; i < segment_count; ++i )
{
if ( end - it < 12 ) return false;
it += 4;
uint32_t segment_size = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
it += 4;
std::vector<uint8_t>::const_iterator segment_end = it + segment_size;
while ( it < segment_end && it < body_end )
while ( it != segment_end && it != body_end )
{
if ( segment_end - it < 4 ) return false;
uint32_t delta = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
it += 4;
uint32_t event;
current_timestamp += delta;
if ( !is_eight_byte ) it += 4;
if ( !is_eight_byte )
{
if ( segment_end - it < 4 ) return false;
it += 4;
}
if ( segment_end - it < 4 ) return false;
event = it[ 0 ] | ( it[ 1 ] << 8 ) | ( it[ 2 ] << 16 ) | ( it[ 3 ] << 24 );
it += 4;
if ( event >> 24 == 0x01 )

View File

@ -35,11 +35,14 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
uint8_t velocity_levels[ 16 ] = { 0 };
if ( offset >= p_file.size() || offset + length > p_file.size() )
return false;
std::vector<uint8_t>::const_iterator it = p_file.begin() + offset, end = p_file.begin() + offset + length;
uint8_t buffer[ 4 ];
while ( it < end )
while ( it != end )
{
buffer[ 0 ] = *it++;
if ( buffer[ 0 ] == 0x60 ) break;
@ -56,6 +59,7 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
{
case 0x00:
type = midi_event::note_on;
if ( it == end ) return false;
buffer[ 1 ] = *it++;
buffer[ 2 ] = 0;
bytes_to_write = 2;
@ -63,9 +67,11 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
case 0x10:
type = midi_event::note_on;
if ( it == end ) return false;
buffer[ 1 ] = *it++;
if ( buffer[ 1 ] & 0x80 )
{
if ( it == end ) return false;
buffer[ 2 ] = *it++;
velocity_levels[ channel ] = buffer[ 2 ];
buffer[ 1 ] &= 0x7F;
@ -79,6 +85,7 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
case 0x20:
type = midi_event::pitch_wheel;
if ( it == end ) return false;
buffer[ 1 ] = *it++;
buffer[ 2 ] = buffer[ 1 ] >> 1;
buffer[ 1 ] <<= 7;
@ -87,6 +94,7 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
case 0x30:
type = midi_event::control_change;
if ( it == end ) return false;
buffer[ 1 ] = *it++;
if ( buffer[ 1 ] >= 10 && buffer[ 1 ] <= 14 )
{
@ -98,6 +106,7 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
break;
case 0x40:
if ( it == end ) return false;
buffer[ 1 ] = *it++;
if ( buffer[ 1 ] )
{
@ -105,6 +114,7 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
{
type = midi_event::control_change;
buffer[ 1 ] = mus_controllers[ buffer[ 1 ] ];
if ( it == end ) return false;
buffer[ 2 ] = *it++;
bytes_to_write = 2;
}
@ -113,6 +123,7 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
else
{
type = midi_event::program_change;
if ( it == end ) return false;
buffer[ 1 ] = *it++;
bytes_to_write = 1;
}
@ -126,7 +137,7 @@ bool midi_processor::process_mus( std::vector<uint8_t> const& p_file, midi_conta
if ( buffer[ 0 ] & 0x80 )
{
int delta = decode_delta( it );
int delta = decode_delta( it, end );
if ( delta < 0 ) return false; /*throw exception_io_data( "Invalid MUS delta" );*/
current_timestamp += delta;
}

View File

@ -41,10 +41,6 @@ static const char * riff_tag_mappings[][2] =
{ "ITCH", "technician" }
};
#define CF_TEXT 1
#define CF_TIFF 6
#define CF_DIB 8
bool midi_processor::process_riff_midi( std::vector<uint8_t> const& p_file, midi_container & p_out )
{
uint32_t file_size = p_file[ 4 ] | ( p_file[ 5 ] << 8 ) | ( p_file[ 6 ] << 16 ) | ( p_file[ 7 ] << 24 );
@ -60,9 +56,11 @@ bool midi_processor::process_riff_midi( std::vector<uint8_t> const& p_file, midi
std::vector<uint8_t> extra_buffer;
while ( it < body_end )
while ( it != body_end )
{
if ( body_end - it < 8 ) return false;
uint32_t chunk_size = it[ 4 ] | ( it[ 5 ] << 8 ) | ( it[ 6 ] << 16 ) | ( it[ 7 ] << 24 );
if ( (unsigned long)(body_end - it) < chunk_size ) return false;
if ( it[ 0 ] == 'd' && it[ 1 ] == 'a' && it[ 2 ] == 't' && it[ 3 ] == 'a' )
{
if ( !found_data )
@ -74,52 +72,19 @@ bool midi_processor::process_riff_midi( std::vector<uint8_t> const& p_file, midi
}
else return false; /*throw exception_io_data( "Multiple RIFF data chunks found" );*/
it += 8 + chunk_size;
if ( chunk_size & 1 && it < body_end ) ++it;
if ( chunk_size & 1 && it != body_end ) ++it;
}
else if ( it[ 0 ] == 'D' && it[ 1 ] == 'I' && it[ 2 ] == 'S' && it[ 3 ] == 'P' )
{
uint32_t type = it[ 8 ] | ( it[ 9 ] << 8 ) | ( it[ 10 ] << 16 ) | ( it[ 11 ] << 24 );
if ( type == CF_TEXT )
if ( type == 1 )
{
extra_buffer.resize( chunk_size - 4 );
std::copy( it + 12, it + 8 + chunk_size, extra_buffer.begin() );
meta_data.add_item( midi_meta_data_item( 0, "display_name", (const char *) &extra_buffer[0] ) );
}
else if ( type == CF_TIFF )
{
meta_data.assign_bitmap( it + 12, it + 8 + chunk_size );
}
else if ( type == CF_DIB )
{
if ( chunk_size >= 8 )
{
uint32_t dib_header_size = it[ 12 ] | ( it[13] << 8 ) | ( it[14] << 16 ) | ( it[15] << 24 );
if ( chunk_size >= 4 + dib_header_size )
{
uint32_t dib_image_offset = 14 + dib_header_size;
uint32_t dib_size = chunk_size + 10;
extra_buffer.resize( dib_size );
extra_buffer[ 0 ] = 'B';
extra_buffer[ 1 ] = 'M';
extra_buffer[ 2 ] = dib_size;
extra_buffer[ 3 ] = dib_size >> 8;
extra_buffer[ 4 ] = dib_size >> 16;
extra_buffer[ 5 ] = dib_size >> 24;
extra_buffer[ 6 ] = 0;
extra_buffer[ 7 ] = 0;
extra_buffer[ 8 ] = 0;
extra_buffer[ 9 ] = 0;
extra_buffer[ 10 ] = dib_image_offset;
extra_buffer[ 11 ] = dib_image_offset >> 8;
extra_buffer[ 12 ] = dib_image_offset >> 16;
extra_buffer[ 13 ] = dib_image_offset >> 24;
std::copy(it + 12, it + 8 + chunk_size, extra_buffer.begin() + 14);
meta_data.assign_bitmap(extra_buffer.begin(), extra_buffer.end());
}
}
}
it += 8 + chunk_size;
if ( chunk_size & 1 && it < body_end ) ++it;
if ( chunk_size & 1 && it != body_end ) ++it;
}
else if ( it[ 0 ] == 'L' && it[ 1 ] == 'I' && it[ 2 ] == 'S' && it[ 3 ] == 'T' )
{
@ -128,10 +93,13 @@ bool midi_processor::process_riff_midi( std::vector<uint8_t> const& p_file, midi
{
if ( !found_info )
{
if ( chunk_end - it < 12 ) return false;
it += 12;
while ( it < chunk_end )
while ( it != chunk_end )
{
if ( chunk_end - it < 4 ) return false;
uint32_t field_size = it[ 4 ] | ( it[ 5 ] << 8 ) | ( it[ 6 ] << 16 ) | ( it[ 7 ] << 24 );
if ( (unsigned long)(chunk_end - it) < 8 + field_size ) return false;
std::string field;
field.assign( it, it + 4 );
for ( unsigned i = 0; i < _countof(riff_tag_mappings); ++i )
@ -146,7 +114,7 @@ bool midi_processor::process_riff_midi( std::vector<uint8_t> const& p_file, midi
std::copy( it + 8, it + 8 + field_size, extra_buffer.begin() );
it += 8 + field_size;
meta_data.add_item( midi_meta_data_item( 0, field.c_str(), ( const char * ) &extra_buffer[0] ) );
if ( field_size & 1 && it < chunk_end ) ++it;
if ( field_size & 1 && it != chunk_end ) ++it;
}
found_info = true;
}
@ -154,12 +122,12 @@ bool midi_processor::process_riff_midi( std::vector<uint8_t> const& p_file, midi
}
else return false; /* unknown LIST chunk */
it = chunk_end;
if ( chunk_size & 1 && it < body_end ) ++it;
if ( chunk_size & 1 && it != body_end ) ++it;
}
else
{
it += chunk_size;
if ( chunk_size & 1 && it < body_end ) ++it;
if ( chunk_size & 1 && it != body_end ) ++it;
}
if ( found_data && found_info ) break;

View File

@ -20,9 +20,9 @@ bool midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
for (;;)
{
if ( !needs_end_marker && it >= end ) break;
int delta = decode_delta( it );
if ( !needs_end_marker && it >= end ) break;
if ( !needs_end_marker && it == end ) break;
int delta = decode_delta( it, end );
if ( !needs_end_marker && it == end ) break;
if ( delta < 0 )
{
@ -45,6 +45,7 @@ bool midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
if ( !needs_end_marker && ( event_code & 0xF0 ) == 0xE0 ) continue;
if ( data_bytes_read < 1 )
{
if ( it == end ) return false;
buffer[ 0 ] = *it++;
++data_bytes_read;
}
@ -54,6 +55,7 @@ bool midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
case 0xD0:
break;
default:
if ( it == end ) return false;
buffer[ data_bytes_read ] = *it++;
++data_bytes_read;
}
@ -61,8 +63,9 @@ bool midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
}
else if ( event_code == 0xF0 )
{
int data_count = decode_delta( it );
int data_count = decode_delta( it, end );
if ( data_count < 0 ) return false; /*throw exception_io_data( "Invalid System Exclusive message" );*/
if ( end - it > data_count ) return false;
buffer.resize( data_count + 1 );
buffer[ 0 ] = 0xF0;
std::copy( it, it + data_count, buffer.begin() + 1 );
@ -71,9 +74,11 @@ bool midi_processor::process_standard_midi_track( std::vector<uint8_t>::const_it
}
else if ( event_code == 0xFF )
{
if ( it == end ) return false;
unsigned char meta_type = *it++;
int data_count = decode_delta( it );
int data_count = decode_delta( it, end );
if ( data_count < 0 ) return false; /*throw exception_io_data( "Invalid meta message" );*/
if ( end - it < data_count ) return false;
buffer.resize( data_count + 2 );
buffer[ 0 ] = 0xFF;
buffer[ 1 ] = meta_type;
@ -112,6 +117,7 @@ bool midi_processor::process_standard_midi( std::vector<uint8_t> const& p_file,
if ( p_file[ 4 ] != 0 || p_file[ 5 ] != 0 || p_file[ 6 ] != 0 || p_file[ 7 ] != 6 ) return false; /*throw exception_io_data("Bad MIDI header size");*/
std::vector<uint8_t>::const_iterator it = p_file.begin() + 8;
std::vector<uint8_t>::const_iterator end = p_file.end();
uint16_t form = ( it[0] << 8 ) | it[1];
if ( form > 2 ) return false;
@ -127,9 +133,11 @@ bool midi_processor::process_standard_midi( std::vector<uint8_t> const& p_file,
for ( std::size_t i = 0; i < track_count; ++i )
{
if ( end - it < 8 ) return false;
if ( it[0] != 'M' || it[1] != 'T' || it[2] != 'r' || it[3] != 'k' ) return false;
uint32_t track_size = ( it[4] << 24 ) | ( it[5] << 16 ) | ( it[6] << 8 ) | it[7];
if ( (unsigned long)(end - it) < track_size ) return false;
it += 8;

View File

@ -16,15 +16,17 @@ const uint8_t midi_processor::xmi_default_tempo[5] = {0xFF, 0x51, 0x07, 0xA1, 0x
unsigned midi_processor::decode_xmi_delta( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end )
{
unsigned delta = 0;
if ( it == end ) return 0;
uint8_t byte = *it++;
if ( !( byte & 0x80 ) )
{
do
{
delta += byte;
if ( it == end ) break;
byte = *it++;
}
while ( !( byte & 0x80 ) && it < end );
while ( !( byte & 0x80 ) && it != end );
}
--it;
return delta;
@ -101,9 +103,11 @@ struct iff_stream
static bool read_iff_chunk( std::vector<uint8_t>::const_iterator & it, std::vector<uint8_t>::const_iterator end, iff_chunk & p_out, bool first_chunk )
{
if ( end - it < 8 ) return false;
std::copy( it, it + 4, p_out.m_id );
it += 4;
uint32_t chunk_size = ( it[ 0 ] << 24 ) | ( it[ 1 ] << 16 ) | ( it[ 2 ] << 8 ) | it[ 3 ];
if ( (unsigned long)(end - it) < chunk_size ) return false;
it += 4;
bool is_cat_chunk = !memcmp( p_out.m_id, "CAT ", 4 );
bool is_form_chunk = !memcmp( p_out.m_id, "FORM", 4 );
@ -111,6 +115,7 @@ static bool read_iff_chunk( std::vector<uint8_t>::const_iterator & it, std::vect
if ( chunk_size > chunk_size_limit ) chunk_size = (uint32_t) chunk_size_limit;
if ( ( first_chunk && is_form_chunk ) || ( !first_chunk && is_cat_chunk ) )
{
if ( end - it < 4 ) return false;
std::vector<uint8_t>::const_iterator chunk_end = it + chunk_size;
std::copy( it, it + 4, p_out.m_type );
it += 4;
@ -121,13 +126,13 @@ static bool read_iff_chunk( std::vector<uint8_t>::const_iterator & it, std::vect
p_out.m_sub_chunks.push_back( chunk );
}
it = chunk_end;
if ( chunk_size & 1 && it < end ) ++it;
if ( chunk_size & 1 && it != end ) ++it;
}
else if ( !is_form_chunk && !is_cat_chunk )
{
p_out.m_data.assign( it, it + chunk_size );
it += chunk_size;
if ( chunk_size & 1 && it < end ) ++it;
if ( chunk_size & 1 && it != end ) ++it;
}
else
{
@ -142,7 +147,7 @@ static bool read_iff_stream( std::vector<uint8_t> const& p_file, iff_stream & p_
{
std::vector<uint8_t>::const_iterator it = p_file.begin(), end = p_file.end();
bool first_chunk = true;
while ( it < end )
while ( it != end )
{
iff_chunk chunk;
if ( !read_iff_chunk( it, end, chunk, first_chunk ) ) return false;
@ -189,7 +194,7 @@ bool midi_processor::process_xmi( std::vector<uint8_t> const& p_file, midi_conta
std::vector<uint8_t>::const_iterator it = event_body.begin(), end = event_body.end();
while ( it < end )
while ( it != end )
{
unsigned delta = decode_xmi_delta( it, end );
current_timestamp += delta;
@ -199,19 +204,22 @@ bool midi_processor::process_xmi( std::vector<uint8_t> const& p_file, midi_conta
last_event_timestamp = current_timestamp;
}
if ( it == end ) return false;
buffer[ 0 ] = *it++;
if ( buffer[ 0 ] == 0xFF )
{
if ( it == end ) return false;
buffer[ 1 ] = *it++;
int meta_count;
long meta_count;
if ( buffer[ 1 ] == 0x2F )
{
meta_count = 0;
}
else
{
meta_count = decode_delta( it );
meta_count = decode_delta( it, end );
if ( meta_count < 0 ) return false; /*throw exception_io_data( "Invalid XMI meta message" );*/
if ( end - it < meta_count ) return false;
buffer.resize( meta_count + 2 );
std::copy( it, it + meta_count, buffer.begin() + 2 );
it += meta_count;
@ -235,8 +243,9 @@ bool midi_processor::process_xmi( std::vector<uint8_t> const& p_file, midi_conta
}
else if ( buffer[ 0 ] == 0xF0 )
{
int system_exclusive_count = decode_delta( it );
long system_exclusive_count = decode_delta( it, end );
if ( system_exclusive_count < 0 ) return false; /*throw exception_io_data( "Invalid XMI System Exclusive message" );*/
if ( end - it < system_exclusive_count ) return false;
buffer.resize( system_exclusive_count + 1 );
std::copy( it, it + system_exclusive_count, buffer.begin() + 1 );
it += system_exclusive_count;
@ -245,11 +254,13 @@ bool midi_processor::process_xmi( std::vector<uint8_t> const& p_file, midi_conta
else if ( buffer[ 0 ] >= 0x80 && buffer[ 0 ] <= 0xEF )
{
unsigned bytes_read = 1;
if ( it == end ) return false;
buffer[ 1 ] = *it++;
midi_event::event_type type = (midi_event::event_type)( ( buffer[ 0 ] >> 4 ) - 8 );
unsigned channel = buffer[ 0 ] & 0x0F;
if ( type != midi_event::program_change && type != midi_event::channel_aftertouch )
{
if ( it == end ) return false;
buffer[ 2 ] = *it++;
bytes_read = 2;
}
@ -257,7 +268,7 @@ bool midi_processor::process_xmi( std::vector<uint8_t> const& p_file, midi_conta
if ( type == midi_event::note_on )
{
buffer[ 2 ] = 0x00;
int note_length = decode_delta( it );
int note_length = decode_delta( it, end );
if ( note_length < 0 ) return false; /*throw exception_io_data( "Invalid XMI note message" );*/
unsigned note_end_timestamp = current_timestamp + note_length;
if ( note_end_timestamp > last_event_timestamp ) last_event_timestamp = note_end_timestamp;