Page MenuHomePhabricator

BlueBerry abort on application launch if path contains special characters
Closed, ResolvedPublic

Description

Steps to reproduce:

  1. unpack the installer to a path that contains non-ASCII characters (e.g. "Arbeitsfläche" which is the Desktop on a German localized Ubuntu).
  2. ./mitkWorkbench.sh

Result: abort
Expected result: Application should launch

Event Timeline

Tried to install to
/+~äöß井戸端Новые страницы'#/
under windows 7 64 bit, the resulting path was
/+~äöß '#/
this is probably an error of nsis itself. There seems to be an optional unicode plugin or a unicode build [1].

Continuing testing on the install path /+~äöß '#/ did indeed result in the application not starting.

[1] http://nsis.sourceforge.net/Unicode_plug-in

When trying to create a debug build on both paths there are two more third party problems:

/+~äöß井戸端Новые страницы'#/
CMake does not recognize the unicode characters, they are rendered as ?????.

/+~äöß '#/
CMake tries to create a superbuild binary but fails, as the compilation of the test project fails.

Attached debugger to an executable of a debug installer installed to:
D:\tmp\+~äöß '#
and
D:\tmp\testinstall
for comparison.

When entering berryProvisioningInfo.cpp in the function
QUrl ProvisioningInfo::addPluginToInstall(const QString& file)

I added the following lines of code (first and last line of excerpt are original code):


QFileInfo fileInfo(pluginUrl.toLocalFile());

QString qlocalFile = pluginUrl.toLocalFile();
QString fileName2 = fileInfo.fileName();
QString filePath2 = fileInfo.absolutePath();

if (!fileInfo.exists())

pluginUrl is set by:
QUrl pluginUrl(file);

Comparing the two installs, the first time the function is entered:

---------------Special characters---------------
file = "file:///D:/tmp/+~äöß '#/bin/plugins/liborg_commontk_configadmin.dll"
qlocalFile = "D:/tmp/+~äöß '"
fileName2 = "+~äöß '"
filePath2 = "D:/tmp"
---------------alphabet only--------------------
file = "file:///D:/tmp/testinstall/bin/plugins/liborg_commontk_eventadmin.dll"
qlocalFile = "D:/tmp/testinstall/bin/plugins/liborg_commontk_eventadmin.dll"
fileName2 = "liborg_commontk_eventadmin.dll"
filePath2 = "D:/tmp/testinstall/bin/plugins"

Changing the test path from
D:\tmp\+~äöß '#
to
D:\tmp\+~äöß '

The # character denotes a url fragment, which will be handled by QUrl accordingly [1]. As there seems to be no easy way to 1. escape the # character and 2. still create a valid local file path this was decided to be a known issue.

[1] http://qt-project.org/doc/qt-5.0/qtcore/qurl.html#fragment

Using the current master installing a release installer to
D:/tmp/ÄrbeitsFläche
seems to work fine under Windows.

Debug installers crash on both test paths.

Tested on linux, two different install directories, special characters lead to abort:

x@y:/tmp/TestVerzeichnissÜßä/MITK-2013.09.99_r667b3f-linux64$ ./mitkWorkbench.sh --BlueBerry.clean
*Wed Oct 30 15:32:05 2013
0.360* [BlueBerry] FATAL: The org.blueberry.osgi plug-in is not started. Check that your application loads the correct provisioning file and that it contains an entry for the org.blueberry.osgi plug-in.

When installed into /tmp directly, the application runs fine.

Crashes in
MITK\BlueBerry\Bundles\org.blueberry.osgi\src\berryBundleLoader.cpp

in function

void BundleLoader::ReadContributions(IBundle::Pointer bundle)

the call

IExtensionPointService::Pointer service = Platform::GetExtensionPointService();

returns a service that is unexpectedly NULL.

New remote branch pushed: bug-16224-BerryCrashUmlauts

Unfortunately the proposed change in the pushed branch results in the Windows application crashing instead.

The problem appears to be, that the encoding of argv is not fixed. Ideally we should try to convert argv to a fixed encoding (I propose utf8) before handing it through to the QtSafeApplication.

This fix would be implemented before the first command in each applications main function. As an example in the mitkWorkbench.cpp the code currently is:

int main(int argc, char** argv)
{

// Create a QApplication instance first
QtSafeApplication qSafeApp(argc, argv);

...
}

Regardging the encodings of argv, taken from [1]

  1. As discussed, on Windows the argv is encoded using the current code page. However, you can retrieve the command line as UTF-16 using GetCommandLineW. Use of argv is not recommended for modern Windows apps with unicode support because code pages are deprecated.
  1. On Unixes, the argv has no fixed encoding:

    a) File names inserted by tab-completion/globbing will occur in argv verbatim as exactly the byte sequences by which they are named on disk. This is true even if those byte sequences make no sense in the current locale.

    b) Input entered directly by the user using their IME will occur in argv in the locale encoding. (Ubuntu seems to use LOCALE to decide how to encode IME input, whereas OS X uses the Terminal.app encoding Preference.)

A comment later in the cited thread points out Windows always uses UTF-16, whenever possible.

[1] http://stackoverflow.com/questions/5408730/what-is-the-encoding-of-argv

Further googling does not seem to reveal a one size fits all solution.

While modern *Nixes switch to utf-8 more and more theoretically the caller could have any encoding, even worse, due to auto completion the the encoding of the characters might even be different from the encoding the shell actually uses.

Therefore I would suggest the following:

  1. Windows: Get as utf-16 and convert to utf-8
  2. Linux/Mac: Assume it is going to be utf-8

Then we can add error handling if the provisioning file can not be opened and display some sensible error message instead of crashing.

Your thoughts?

The latest stand of the remote branch contains a quick fix for the problem so we have something running for the upcoming release ( Caspar is testing the fix on Windows )

  1. Use ifdefs provided by Qt to distinguish between WIN and *NIX systems in order to use different encodings when handling the path to the provisioning file.
  2. throw an exception in berry::InternalPlatform::Initialize in case no provisioning file was found ( i.e. the PluginDirs QStringList is empty )
  3. catch the exception from (2) in the berry::Starter in order to terminate the application properly

The exception in (2) can occur if the locale is not set properly, i.e. setting the variable LANG="" and starting from a directory with special characters in path. In this case, the fromUtf8 string converting won't work.

For final fix: try different encodings until the provisioning file can be loaded. But it has still be discussed what should happen, if this fails for each encoding - maybe use some 'dummy' provisioning file?

I have discussed the quick solution with Marco, the fix got approved for release. Setting flag+.

[7542fb]: Merge branch 'bug-16224-BerryCrashUmlauts'

Merged commits:

2013-11-27 13:44:45 Jan Hering [e7d38b]
Better error message


2013-11-20 17:50:41 Jan Hering [a7201d]
Quick'n'dirty hack for special characters

  • platform specific encoding in QString
  • checking for empty plugin directories & throwing exceptions
  • exception handling in platform starter

2013-11-13 17:29:40 Jan Hering [868655]
Converting to QString with utf8 enc