Fixed problem where importing invalid midi files caused crash.

This commit is contained in:
Damien Zammit 2014-04-29 06:44:40 +10:00
parent f5276a104c
commit 2f6065b32c
5 changed files with 39 additions and 4 deletions

View file

@ -279,7 +279,7 @@ SoundFileBox::setup_labels (const string& filename)
string error_msg; string error_msg;
if (SMFSource::safe_midi_file_extension (path)) { if (SMFSource::valid_midi_file (path)) {
boost::shared_ptr<SMFSource> ms = boost::shared_ptr<SMFSource> ms =
boost::dynamic_pointer_cast<SMFSource> ( boost::dynamic_pointer_cast<SMFSource> (
@ -404,7 +404,7 @@ SoundFileBox::audition ()
boost::shared_ptr<Region> r; boost::shared_ptr<Region> r;
if (SMFSource::safe_midi_file_extension (path)) { if (SMFSource::valid_midi_file (path)) {
boost::shared_ptr<SMFSource> ms = boost::shared_ptr<SMFSource> ms =
boost::dynamic_pointer_cast<SMFSource> ( boost::dynamic_pointer_cast<SMFSource> (
@ -1307,7 +1307,7 @@ SoundFileOmega::reset_options ()
/* See if we are thinking about importing any MIDI files */ /* See if we are thinking about importing any MIDI files */
vector<string>::iterator i = paths.begin (); vector<string>::iterator i = paths.begin ();
while (i != paths.end() && SMFSource::safe_midi_file_extension (*i) == false) { while (i != paths.end() && SMFSource::valid_midi_file (*i) == false) {
++i; ++i;
} }
bool const have_a_midi_file = (i != paths.end ()); bool const have_a_midi_file = (i != paths.end ());
@ -1535,7 +1535,7 @@ SoundFileOmega::check_info (const vector<string>& paths, bool& same_size, bool&
src_needed = true; src_needed = true;
} }
} else if (SMFSource::safe_midi_file_extension (*i)) { } else if (SMFSource::valid_midi_file (*i)) {
Evoral::SMF reader; Evoral::SMF reader;
reader.open(*i); reader.open(*i);

View file

@ -77,6 +77,7 @@ public:
void ensure_disk_file (); void ensure_disk_file ();
static bool safe_midi_file_extension (const std::string& path); static bool safe_midi_file_extension (const std::string& path);
static bool valid_midi_file (const std::string& path);
void prevent_deletion (); void prevent_deletion ();

View file

@ -34,6 +34,7 @@
#include <glibmm/fileutils.h> #include <glibmm/fileutils.h>
#include "evoral/Control.hpp" #include "evoral/Control.hpp"
#include "evoral/evoral/SMF.hpp"
#include "ardour/event_type_map.h" #include "ardour/event_type_map.h"
#include "ardour/midi_model.h" #include "ardour/midi_model.h"
@ -48,6 +49,7 @@
using namespace ARDOUR; using namespace ARDOUR;
using namespace Glib; using namespace Glib;
using namespace PBD; using namespace PBD;
using namespace Evoral;
/** Constructor used for new internal-to-session files. File cannot exist. */ /** Constructor used for new internal-to-session files. File cannot exist. */
SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags) SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
@ -496,6 +498,15 @@ SMFSource::mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::Musical
mark_nonremovable (); mark_nonremovable ();
} }
bool
SMFSource::valid_midi_file (const string& file)
{
if (safe_midi_file_extension (file) ) {
return (SMF::test (file) );
}
return false;
}
bool bool
SMFSource::safe_midi_file_extension (const string& file) SMFSource::safe_midi_file_extension (const string& file)
{ {

View file

@ -50,6 +50,7 @@ public:
SMF() : _smf(0), _smf_track(0), _empty(true) {}; SMF() : _smf(0), _smf_track(0), _empty(true) {};
virtual ~SMF(); virtual ~SMF();
static bool test(const std::string& path);
int open(const std::string& path, int track=1) THROW_FILE_ERROR; int open(const std::string& path, int track=1) THROW_FILE_ERROR;
int create(const std::string& path, int track=1, uint16_t ppqn=19200) THROW_FILE_ERROR; int create(const std::string& path, int track=1, uint16_t ppqn=19200) THROW_FILE_ERROR;
void close() THROW_FILE_ERROR; void close() THROW_FILE_ERROR;

View file

@ -67,6 +67,28 @@ SMF::seek_to_track(int track)
} }
} }
/** Attempt to open the SMF file just to see if it is valid.
*
* \return true on success
* false on failure
*/
bool
SMF::test(const std::string& path)
{
PBD::StdioFileDescriptor d (path, "r");
FILE* f = d.allocate ();
if (f == 0) {
return false;
}
smf_t* test_smf;
if ((test_smf = smf_load (f)) == NULL) {
return false;
}
smf_delete (test_smf);
return true;
}
/** Attempt to open the SMF file for reading and/or writing. /** Attempt to open the SMF file for reading and/or writing.
* *
* \return 0 on success * \return 0 on success