Don't allow invalid project files! #2523

Merged
merged 1 commit into from Sep 5, 2016

Projects

None yet

5 participants

@zonkmachine
Member

The renderer hangs bad if you give it something that isn't an LMMS project as argument.


Loading project...
Done
|-                                 |      0%   \   <---infinite hang here!

This fix tests that the given file is really a file ( not a directory ). It also tests for a valid LMMS project suffix.

~/builds/lmms/build$ ./lmms -r ../build
The file ../build does not exist!

You can test specifically for if the argument is a directory and report accordingly but that would be over doing it a bit I think.

~/builds/lmms/build$ ./lmms -r ../build/lmmscon
The file ../build/lmmscon does not exist!
~/builds/lmms/build$ ./lmms -r ../build/lmmsconfig.h 
../build/lmmsconfig.h is not an LMMS project fil

I finally moved the line Engine::init( true ); to after the tests as it just felt like a better place.

@zonkmachine zonkmachine added the bug label Jan 28, 2016
@zonkmachine zonkmachine added this to the 1.2.0 milestone Jan 28, 2016
@zonkmachine zonkmachine changed the title from Don't allow crap as render argument! to Don't allow invalid arguments to the renderer! Jan 28, 2016
@tresf
Member
tresf commented Jan 28, 2016

Looks good. 👍 I'll leave time for comments. One thought was the posiblity of loading a non-mmp or non-mmpz file, but loadFile only takes projects, so that's for another time. 👍

@zonkmachine
Member

One thought was the posiblity of loading a non-mmp or non-mmpz file,

Yes, I was going to ask about it.
I'm currently trying to move the whole file test to here. Right after fileToLoad is assigned a file.
We're currently treating file arguments for render and load differently and this should fix it. It works but I haven't tested it thoroughly. It probably makes the larger part of #2524 redundant

@zonkmachine
Member

In the last version it still tests for an empty fileToLoad if you choose --import and halts with a
The file does not exist!

@zonkmachine zonkmachine changed the title from Don't allow invalid arguments to the renderer! to Don't allow invalid project file arguments! Jan 29, 2016
@zonkmachine zonkmachine changed the title from Don't allow invalid project file arguments! to Don't allow invalid project files! Jan 29, 2016
@zonkmachine
Member

importsuffixes

Same checks for files to import.

@zonkmachine
Member

One thought was the posiblity of loading a non-mmp or non-mmpz file

An mpt file?

@softrabbit
Member

An mpt file?

Any valid LMMS project file that happens to be named differently from what's expected? If I explicitly tell LMMS to load a file called "myproject.mmpx" or whatever, I expect it to at least try and not reject the file until it's at least opened the file and tried parsing it.

@zonkmachine
Member

Any valid LMMS project file that happens to be named differently from what's expected? If I explicitly tell LMMS to load a file called "myproject.mmpx" or whatever, I expect it to at least try and not reject the file until it's at least opened the file and tried parsing it.

OK. Right now if you try and save a project file with another suffix than .mmp or .mmpz, it will stick a new suffix after the one you opted for. In your case with myproject.mmpx you will get myproject.mmpx.mmpz so on my Ubuntu/Mint I have to go back and change suffix manually and then myproject.mmpx will open as you expect it. Either as a command line argument or from the gui.

Edit: Only files ending mmp/mmpz will show up in the file open dialogue so other valid projects will have to be loaded from the command line.

@tresf tresf and 1 other commented on an outdated diff Apr 23, 2016
src/core/main.cpp
+ printf( "The file %s does not exist!\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( fileInfoImport.isDir() )
+ {
+ printf( "%s is a directory!\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( !(
+ fileInfoImport.suffix().toLower() == "mid" ||
+ fileInfoImport.suffix().toLower() == "midi" ||
+ fileInfoImport.suffix().toLower() == "rmi" ||
+ fileInfoImport.suffix().toLower() == "flp" ||
+ fileInfoImport.suffix().toLower() == "h2song" ) )
@tresf
tresf Apr 23, 2016 Member

Hmm.... Every time I see a laundry list of file extensions I get worried that we're making more work for ourselves down the road. 😄 Perhaps related to this PR, perhaps not.... can we start managing our extension in a centralized place? We should be able to use #ifdef's to enable/disable them globally based on what libraries/plugins cmake finds. We already do this in several other places already. Food for thought.

@zonkmachine
zonkmachine May 5, 2016 Member

Perhaps related to this PR, perhaps not.... can we start managing our extension in a centralized place?

Related but it doesn't sound like something I can implement.

@tresf tresf and 2 others commented on an outdated diff Apr 23, 2016
src/core/main.cpp
@@ -528,6 +528,57 @@ int main( int argc, char * * argv )
}
}
+ // Test file argument before continuing
+ QFileInfo fileInfoLoad( fileToLoad );
+ QFileInfo fileInfoImport( fileToImport );
+ if( !fileToLoad.isEmpty() )
@tresf
tresf Apr 23, 2016 Member

Shouldn't this be the other way around? Shouldn't we only instantiate fileInfoLoad if the QString isn't null or empty? This would also remove the need for setting an empty QString above.

@tresf
tresf Jul 5, 2016 Member

The above code comment from April still remains unanswered and you have a commented line that should be removed prior to merging.

@zonkmachine
zonkmachine Jul 18, 2016 Member

Shouldn't we only instantiate fileInfoLoad if the QString isn't null or empty? This would also remove the need for setting an empty QString above.

No, I don't think so, but this part is essentially the same as before. I just moved it and expanded on the functionality.

you have a commented line that should be removed

comment removed

@jasp00
jasp00 Jul 18, 2016 Member

fileInfoLoad should be instantiated in the if( !fileToLoad.isEmpty() ) block; fileInfoImport, in the if( !fileToImport.isEmpty() ) one.

@zonkmachine
zonkmachine Jul 19, 2016 Member

OK. I updated the according to Javiers suggestions.

@zonkmachine
Member

Conflicts resolved.

@Umcaruje
Member
Umcaruje commented Jul 8, 2016

@zonkmachine is there any more work needed to be done here, or it could be tested and merged?

@zonkmachine
Member

Yes, mad sorry about the slow response here. Short on time. I'll look into it as soon as I possibly can.

@zonkmachine
Member

OK. Trying to finish this one now.

@jasp00 jasp00 and 1 other commented on an outdated diff Jul 18, 2016
src/core/main.cpp
+ {
+ if( !fileInfoLoad.exists() )
+ {
+ printf( "The file %s does not exist.\n",
+ fileToLoad.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( fileInfoLoad.isDir() )
+ {
+ printf( "%s is a directory.\n",
+ fileToLoad.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( !( fileInfoLoad.suffix().toLower() == "mmp" ||
+ fileInfoLoad.suffix().toLower() == "mmpz" ||
+ fileInfoLoad.suffix().toLower() == "mpt" ) )
@jasp00
jasp00 Jul 18, 2016 Member

Older projects use the xml extension.

@jasp00 jasp00 and 1 other commented on an outdated diff Jul 18, 2016
src/core/main.cpp
+ if( !fileInfoImport.exists() )
+ {
+ printf( "The file %s does not exist.\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( fileInfoImport.isDir() )
+ {
+ printf( "%s is a directory.\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( !( fileInfoImport.suffix().toLower() == "mid" ||
+ fileInfoImport.suffix().toLower() == "midi" ||
+ fileInfoImport.suffix().toLower() == "rmi" ||
+ fileInfoImport.suffix().toLower() == "flp" ||
@jasp00
jasp00 Jul 18, 2016 Member

FLP is dropped.

@zonkmachine
zonkmachine Jul 19, 2016 Member

Fixed. Should it also drop a message that FruityLoop support is dropped since version 1.2 ?

@jasp00
jasp00 Jul 19, 2016 Member

Such a message is useful before dropping support, when the feature is deprecated. It is not needed now.

@jasp00
Member
jasp00 commented Jul 21, 2016

Current fix is incomplete. Input file could be an empty file, the empty template, a broken project or a different XML file. I do not think these new checks are necessary. The check for empty projects on export should be enough.

@jasp00
Member
jasp00 commented Jul 21, 2016

I do not think these new checks are necessary.

I mean checking the extension, if the input does not exists, etc.

@zonkmachine
Member
zonkmachine commented Aug 9, 2016 edited

Right, back on this...

Input file could be an empty file,

Hm, missed that. Poking around with it right now...

the empty template

...Will open correctly.

a broken project

A file that is empty or a broken project will be passed to LMMS who will fail to open it and report on it.

emptyproject

It will then open an empty project with the title of the project you tried to open.

@jasp00
Member
jasp00 commented Aug 9, 2016

I mean that rendering those invalid projects (empty file, empty template, etc.) with lmms -r causes the infinite hang.

@zonkmachine
Member

Right. In the case of an empty file the latest commit proposed a fix and it's working. An empty template however, I think goes a bit beyond this PR. Shouldn't it rather be catched by the renderer?

@zonkmachine
Member

When exporting from the gui lmms ran TrackContainer::isEmpty() so I added this test in main.


$ ./lmms --rendertracks empty.mmpz
Notice: could not set realtime priority.
VST sync support disabled in your configuration
Loading project...
The project empty.mmpz is empty, aborting!

@jasp00 jasp00 and 1 other commented on an outdated diff Aug 17, 2016
src/core/main.cpp
+ if( !fileInfoLoad.exists() )
+ {
+ printf( "The file %s does not exist.\n",
+ fileToLoad.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( fileInfoLoad.isDir() )
+ {
+ printf( "%s is a directory.\n",
+ fileToLoad.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( !( fileInfoLoad.suffix().toLower() == "mmp" ||
+ fileInfoLoad.suffix().toLower() == "mmpz" ||
+ fileInfoLoad.suffix().toLower() == "mpt" ||
+ fileInfoLoad.suffix().toLower() == "xml" ) )
@jasp00
jasp00 Aug 17, 2016 Member

Having one of these extensions is not required; this check should be removed. The Engine::getSong()->isEmpty() check takes care of invalid projects.

@zonkmachine
zonkmachine Sep 1, 2016 Member

OK. I initially made these suffix tests because lmms opens in an unclean manner when you throw a file whatever at it. It will open a blank project with the title you just gave it. I think at least we should not set the project title when the project couldn't be opened.

@zonkmachine
zonkmachine Sep 1, 2016 Member

It will open a blank project with the title you just gave it. I think at least we should not set the project title when the project couldn't be opened.

That's a regression from 1.1.3 which does this just fine...

@jasp00 jasp00 commented on an outdated diff Aug 17, 2016
src/core/main.cpp
+ if( !fileInfoImport.exists() )
+ {
+ printf( "The file %s does not exist.\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( fileInfoImport.isDir() )
+ {
+ printf( "%s is a directory.\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( !( fileInfoImport.suffix().toLower() == "mid" ||
+ fileInfoImport.suffix().toLower() == "midi" ||
+ fileInfoImport.suffix().toLower() == "rmi" ||
+ fileInfoImport.suffix().toLower() == "h2song" ) )
@jasp00
jasp00 Aug 17, 2016 Member

The import plug-ins know better how to handle these files; this check should be removed. ImportFilter::import() takes care of this.

@jasp00 jasp00 and 1 other commented on an outdated diff Aug 17, 2016
src/core/main.cpp
+ {
+ // Test if render ( coreOnly ) and file is empty.
+ if( coreOnly == true && testFile.size() == 0 )
+ {
+ // is empty
+ printf( "The file %s is empty.\n",
+ fileToLoad.toStdString().c_str() );
+ exit( 1 );
+ }
+ testFile.close();
+ }
+
+ if( !fileToLoad.isEmpty() )
+ {
+ QFileInfo fileInfoLoad( fileToLoad );
+ if( !fileInfoLoad.exists() )
@jasp00
jasp00 Aug 17, 2016 Member

!fileInfoLoad.size() checks if the file does not exist or its size is zero. The error message could be The file %s does not have any content.

@jasp00 jasp00 and 1 other commented on an outdated diff Aug 17, 2016
src/core/main.cpp
+ exit( 1 );
+ }
+ else if( !( fileInfoLoad.suffix().toLower() == "mmp" ||
+ fileInfoLoad.suffix().toLower() == "mmpz" ||
+ fileInfoLoad.suffix().toLower() == "mpt" ||
+ fileInfoLoad.suffix().toLower() == "xml" ) )
+ {
+ printf( "%s is not an LMMS project file.\n",
+ fileToLoad.toStdString().c_str() );
+ exit( 1 );
+ }
+ }
+ else if( !fileToImport.isEmpty() )
+ {
+ QFileInfo fileInfoImport( fileToImport );
+ if( !fileInfoImport.exists() )
@jasp00
jasp00 Aug 17, 2016 Member

!fileInfoImport.size() could be done here.

@jasp00 jasp00 and 1 other commented on an outdated diff Aug 17, 2016
src/core/main.cpp
+ }
+ else if( !fileToImport.isEmpty() )
+ {
+ QFileInfo fileInfoImport( fileToImport );
+ if( !fileInfoImport.exists() )
+ {
+ printf( "The file %s does not exist.\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
+ else if( fileInfoImport.isDir() )
+ {
+ printf( "%s is a directory.\n",
+ fileToImport.toStdString().c_str() );
+ exit( 1 );
+ }
@jasp00
jasp00 Aug 17, 2016 Member

These two tests (size() and isDir()) should be in a function.

@zonkmachine
zonkmachine Sep 1, 2016 Member

Aight! That cleaned things up. The PR shrunk by 50%... :)

@zonkmachine zonkmachine commented on an outdated diff Sep 1, 2016
src/core/main.cpp
@@ -567,6 +588,15 @@ int main( int argc, char * * argv )
}
}
+ // Test file argument before continuing
+ if( !fileToLoad.isEmpty() )
+ {
+ fileCheck( fileToLoad );
+ }
+ if( !fileToImport.isEmpty() )
@zonkmachine
zonkmachine Sep 1, 2016 edited Member
else if

Should I short this one out and give fileToLoad priority?

@zonkmachine
zonkmachine Sep 1, 2016 Member

Yeah, fixed that...

@zonkmachine zonkmachine commented on the diff Sep 1, 2016
src/core/main.cpp
printf( "Loading project...\n" );
Engine::getSong()->loadProject( fileToLoad );
+ if( Engine::getSong()->isEmpty() )
+ {
+ printf("The project %s is empty, aborting!\n", fileToLoad.toUtf8().constData() );
+ exit( EXIT_FAILURE );
+ }
@zonkmachine
zonkmachine Sep 1, 2016 Member

Is exit() even a good way to terminate the application at this point?

@jasp00
jasp00 Sep 4, 2016 Member

You may omit exit() and avoid the export, so an upgraded .lmmsrc.xml can be written, but exit() (or return) is not a bad way.

@zonkmachine
zonkmachine Sep 5, 2016 Member

oK. I just skimmed past some comment on the net that exit() could be a problem with multi threaded applications. I'm happy with .lmmsrc.xml not being written so we keep failing loads from appearing in the recently opened projects list.

@zonkmachine
Member
zonkmachine commented Sep 2, 2016 edited

lmms used to load default.mmp on failing to load a project but this was broken in commit: 2c7036e#diff-1c0d925f7437a8e3a837c0a991b4cf34

I'll try and look into the original issue (Edit: #781) behind that PR

Edit2: Fix for this in #3013

@zonkmachine
Member

It's better to not inflate this PR. The regression in Song.cpp is not directly related to these fixes so I'll treat them separately.

Rebased and squashed! 🚜

@jasp00
Member
jasp00 commented Sep 4, 2016

This request may be merged.

@zonkmachine zonkmachine merged commit a53fd26 into LMMS:master Sep 5, 2016

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
@zonkmachine
Member

🚜

@zonkmachine zonkmachine deleted the zonkmachine:directoryargument branch Sep 5, 2016
@sambler sambler pushed a commit to sambler/lmms that referenced this pull request Sep 19, 2016
sambler Merge branch 'master' into jackmidi
* master: (213 commits)
  Update Pattern and AutomationPattern length (#3037)
  Refresh i18n strings
  Hint text update
  Drop notes with length zero (#3031)
  Background tweak
  Background
  Update Flanger
  Exclude .ts files from the Github linguist
  Redesign Multitap echo (#3008)
  Update i18n source strings
  Extended arpeggiator functions (#2130)
  Fix sample track playback in BB tracks (#3023)
  Sort plug-in embedded resources (#3014)
  Implement version major.minor.release-stage.build (#3011)
  Fix regressions on loading broken projects (#3013)
  Improved file input validation. (#2523)
  Fix sample track view in BB editor (#3002)
  Request change in model when dropping a track (#3000)
  Add LocklessAllocator and use it in LocklessList (#2998)
  Drop forceStep in AutomatableModel (#3010)
  ...
68e72ba
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment