1. Suppose the app developer has two threads with two different instances of QSSlSocket
2. Each thread calls QSslSocket::startClientEncryption(). So far so good.
3. Inside startClientEncryption(), further down the call chain, at line 332 in qsslsocket_openssl.cpp, we iterate over the certificates returned from QSSlSocket::caCertificates(), and we check if they are valid. Those certificates are shared between instances, but since QSslCertificate::isValid() is supposed to be a const operation, there should be no harm in doing this.
The problem is: QSslCertificate::isValid() actually mutates itself
Because after the Comodo incident back in March, QSslCertificate::isValid() now calls isBlacklisted() wich calls serialNumber() which calculates, stores, and returns the serial number. This is a non-const operation on the d-pointer, but since it happens in a const method, the d-pointer is not being detached, ultimately causing a crash since the other thread is doing the same thing.
This is a problem with many methods of QSslCertificate that are marked as const but actually aren't since they use this calculate-and-store-result-on-first-use idiom. If they where using the Q_D macro, this would have been caught by the compiler as a const-corectness error.