Fixed problem where importing invalid midi files caused crash. 3.5.380
authorDamien Zammit <damien@zamaudio.com>
Mon, 28 Apr 2014 20:44:40 +0000 (06:44 +1000)
committerDamien Zammit <damien@zamaudio.com>
Mon, 28 Apr 2014 20:48:29 +0000 (06:48 +1000)
gtk2_ardour/sfdb_ui.cc
libs/ardour/ardour/smf_source.h
libs/ardour/smf_source.cc
libs/evoral/evoral/SMF.hpp
libs/evoral/src/SMF.cpp

index 4b89cd51fe78cf6d30f1d260e7d4346b7afeaeee..6e08617af2ba13a0b80189e8ba2e78895af45a8f 100644 (file)
@@ -279,7 +279,7 @@ SoundFileBox::setup_labels (const string& filename)
 
        string error_msg;
 
-       if (SMFSource::safe_midi_file_extension (path)) {
+       if (SMFSource::valid_midi_file (path)) {
 
                boost::shared_ptr<SMFSource> ms =
                        boost::dynamic_pointer_cast<SMFSource> (
@@ -404,7 +404,7 @@ SoundFileBox::audition ()
 
        boost::shared_ptr<Region> r;
 
-       if (SMFSource::safe_midi_file_extension (path)) {
+       if (SMFSource::valid_midi_file (path)) {
 
                boost::shared_ptr<SMFSource> ms =
                        boost::dynamic_pointer_cast<SMFSource> (
@@ -1307,7 +1307,7 @@ SoundFileOmega::reset_options ()
 
        /* See if we are thinking about importing any MIDI files */
        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;
        }
        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;
                        }
 
-               } else if (SMFSource::safe_midi_file_extension (*i)) {
+               } else if (SMFSource::valid_midi_file (*i)) {
 
                        Evoral::SMF reader;
                        reader.open(*i);
index 9c0a78f2823cd9920d8b4e5c892a711d4e47c6a4..a068a3e3853b648849bc20ed987a2e87105f6a13 100644 (file)
@@ -77,6 +77,7 @@ public:
        void ensure_disk_file ();
 
        static bool safe_midi_file_extension (const std::string& path);
+       static bool valid_midi_file (const std::string& path);
 
        void prevent_deletion ();
 
index d52923c302a17d90dc2c2ebc07473aee23340fb0..c3bc78c83dec8cc94b7f4cea564004de69fd2624 100644 (file)
@@ -34,6 +34,7 @@
 #include <glibmm/fileutils.h>
 
 #include "evoral/Control.hpp"
+#include "evoral/evoral/SMF.hpp"
 
 #include "ardour/event_type_map.h"
 #include "ardour/midi_model.h"
@@ -48,6 +49,7 @@
 using namespace ARDOUR;
 using namespace Glib;
 using namespace PBD;
+using namespace Evoral;
 
 /** Constructor used for new internal-to-session files.  File cannot exist. */
 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 ();
 }
 
+bool
+SMFSource::valid_midi_file (const string& file)
+{
+       if (safe_midi_file_extension (file) ) {
+               return (SMF::test (file) );
+       }
+       return false;
+}
+
 bool
 SMFSource::safe_midi_file_extension (const string& file)
 {
index 8bd05444c45491b1374de1c815e00e069a5896b8..02d0710409b048f0298f3a4ae0480dd474ce87a4 100644 (file)
@@ -50,6 +50,7 @@ public:
        SMF() : _smf(0), _smf_track(0), _empty(true) {};
        virtual ~SMF();
 
+       static bool test(const std::string& path);
        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;
        void close() THROW_FILE_ERROR;
index b84507818c306a752089976e42695ff08c873707..6557a01b800e50e6ec84b4d8ee2f6f83f51a7c64 100644 (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.
  *
  * \return  0 on success