From aaa970fffe904dd4bcaa700fff3942c76b9b124d Mon Sep 17 00:00:00 2001
From: Christian Kandeler <christian.kandeler@digia.com>
Date: Wed, 14 Aug 2013 15:11:27 +0200
Subject: [PATCH] SSH: Add missing library initialization.

Botan requires to be initialized before first use. We do that on-demand,
but currently we miss one of the two places where this is necessary.
The problem only manifests itself with multithreading, because Botan
itself also does an on-demand initialization, but does not guard
against concurrent access when doing so.

Task-number: QTCREATORBUG-9980
Change-Id: Id65c428e3d8842c8a6f16942b11d52412239d3c9
Reviewed-by: David Kaspar <dkaspar@blackberry.com>
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
---
 src/libs/ssh/ssh.pro             |  2 ++
 src/libs/ssh/ssh.qbs             |  1 +
 src/libs/ssh/sshconnection.cpp   | 28 +++++------------
 src/libs/ssh/sshinit.cpp         | 52 ++++++++++++++++++++++++++++++++
 src/libs/ssh/sshinit_p.h         | 36 ++++++++++++++++++++++
 src/libs/ssh/sshkeygenerator.cpp |  2 ++
 6 files changed, 100 insertions(+), 21 deletions(-)
 create mode 100644 src/libs/ssh/sshinit.cpp
 create mode 100644 src/libs/ssh/sshinit_p.h

diff --git a/src/libs/ssh/ssh.pro b/src/libs/ssh/ssh.pro
index 80379d01b4..511d31b1cf 100644
--- a/src/libs/ssh/ssh.pro
+++ b/src/libs/ssh/ssh.pro
@@ -27,6 +27,7 @@ SOURCES = $$PWD/sshsendfacility.cpp \
     $$PWD/sshkeypasswordretriever.cpp \
     $$PWD/sftpfilesystemmodel.cpp \
     $$PWD/sshkeycreationdialog.cpp \
+    $$PWD/sshinit.cpp \
     $$PWD/sshdirecttcpiptunnel.cpp
 
 HEADERS = $$PWD/sshsendfacility_p.h \
@@ -62,6 +63,7 @@ HEADERS = $$PWD/sshsendfacility_p.h \
     $$PWD/sshkeycreationdialog.h \
     $$PWD/ssh_global.h \
     $$PWD/sshdirecttcpiptunnel_p.h \
+    $$PWD/sshinit_p.h \
     $$PWD/sshdirecttcpiptunnel.h
 
 FORMS = $$PWD/sshkeycreationdialog.ui
diff --git a/src/libs/ssh/ssh.qbs b/src/libs/ssh/ssh.qbs
index 34ae382c3a..d02a19eaee 100644
--- a/src/libs/ssh/ssh.qbs
+++ b/src/libs/ssh/ssh.qbs
@@ -29,6 +29,7 @@ QtcLibrary {
         "ssherrors.h",
         "sshexception_p.h",
         "sshincomingpacket_p.h", "sshincomingpacket.cpp",
+        "sshinit_p.h", "sshinit.cpp",
         "sshkeycreationdialog.cpp", "sshkeycreationdialog.h", "sshkeycreationdialog.ui",
         "sshkeyexchange.cpp", "sshkeyexchange_p.h",
         "sshkeygenerator.cpp", "sshkeygenerator.h",
diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp
index 6e4fecb318..f71b27e960 100644
--- a/src/libs/ssh/sshconnection.cpp
+++ b/src/libs/ssh/sshconnection.cpp
@@ -36,6 +36,7 @@
 #include "sshcryptofacility_p.h"
 #include "sshdirecttcpiptunnel.h"
 #include "sshexception_p.h"
+#include "sshinit_p.h"
 #include "sshkeyexchange_p.h"
 #include "sshremoteprocess.h"
 
@@ -60,26 +61,7 @@
 
 namespace QSsh {
 
-namespace {
-    const QByteArray ClientId("SSH-2.0-QtCreator\r\n");
-
-    bool staticInitializationsDone = false;
-    QMutex staticInitMutex;
-
-    void doStaticInitializationsIfNecessary()
-    {
-        QMutexLocker locker(&staticInitMutex);
-        if (!staticInitializationsDone) {
-            Botan::LibraryInitializer::initialize("thread_safe=true");
-            qRegisterMetaType<QSsh::SshError>("QSsh::SshError");
-            qRegisterMetaType<QSsh::SftpJobId>("QSsh::SftpJobId");
-            qRegisterMetaType<QSsh::SftpFileInfo>("QSsh::SftpFileInfo");
-            qRegisterMetaType<QList <QSsh::SftpFileInfo> >("QList<QSsh::SftpFileInfo>");
-            staticInitializationsDone = true;
-        }
-    }
-} // anonymous namespace
-
+const QByteArray ClientId("SSH-2.0-QtCreator\r\n");
 
 SshConnectionParameters::SshConnectionParameters() :
     timeout(0),  authenticationType(AuthenticationTypePublicKey), port(0)
@@ -112,7 +94,11 @@ bool operator!=(const SshConnectionParameters &p1, const SshConnectionParameters
 SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject *parent)
     : QObject(parent)
 {
-    doStaticInitializationsIfNecessary();
+    Internal::initSsh();
+    qRegisterMetaType<QSsh::SshError>("QSsh::SshError");
+    qRegisterMetaType<QSsh::SftpJobId>("QSsh::SftpJobId");
+    qRegisterMetaType<QSsh::SftpFileInfo>("QSsh::SftpFileInfo");
+    qRegisterMetaType<QList <QSsh::SftpFileInfo> >("QList<QSsh::SftpFileInfo>");
 
     d = new Internal::SshConnectionPrivate(this, serverInfo);
     connect(d, SIGNAL(connected()), this, SIGNAL(connected()),
diff --git a/src/libs/ssh/sshinit.cpp b/src/libs/ssh/sshinit.cpp
new file mode 100644
index 0000000000..c1d4f4ae38
--- /dev/null
+++ b/src/libs/ssh/sshinit.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "sshinit_p.h"
+
+#include <botan/botan.h>
+
+#include <QMutex>
+#include <QMutexLocker>
+
+namespace QSsh {
+namespace Internal {
+
+static bool initialized = false;
+static QMutex initMutex;
+
+void initSsh()
+{
+    QMutexLocker locker(&initMutex);
+    if (!initialized) {
+        Botan::LibraryInitializer::initialize("thread_safe=true");
+        initialized = true;
+    }
+}
+
+} // namespace Internal
+} // namespace QSsh
diff --git a/src/libs/ssh/sshinit_p.h b/src/libs/ssh/sshinit_p.h
new file mode 100644
index 0000000000..af8126803d
--- /dev/null
+++ b/src/libs/ssh/sshinit_p.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+namespace QSsh {
+namespace Internal {
+
+void initSsh();
+
+} // namespace Internal
+} // namespace QSsh
diff --git a/src/libs/ssh/sshkeygenerator.cpp b/src/libs/ssh/sshkeygenerator.cpp
index 992cef1607..395057ae78 100644
--- a/src/libs/ssh/sshkeygenerator.cpp
+++ b/src/libs/ssh/sshkeygenerator.cpp
@@ -31,6 +31,7 @@
 
 #include "sshbotanconversions_p.h"
 #include "sshcapabilities_p.h"
+#include "sshinit_p.h"
 #include "sshpacket_p.h"
 
 #include <botan/botan.h>
@@ -47,6 +48,7 @@ using namespace Internal;
 
 SshKeyGenerator::SshKeyGenerator() : m_type(Rsa)
 {
+    initSsh();
 }
 
 bool SshKeyGenerator::generateKeys(KeyType type, PrivateKeyFormat format, int keySize,
-- 
GitLab