Dear Crypo++ mainteners,

We experienced several cases of crashes in the constructor of the Base64 
class. The problem arises when constructing CryptoPP::Base64Decoder in 
parallel in 2 threads for the first time in a program. We identified the 
race condition:

The constructor of Base64Decoder calls GetDecodingLookupArray:

class Base64Decoder : public BaseN_Decoder
{
public:
        Base64Decoder(BufferedTransformation *attachment = NULL)
                : BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {}
        void IsolatedInitialize(const NameValuePairs &parameters) {}
private:
        static const int * CRYPTOPP_API GetDecodingLookupArray();
};

GetDecodingLookupArray initializes a static structure, and the 
initialization is protected by a racy mechanism:

const int *Base64Decoder::GetDecodingLookupArray()
{
        static volatile bool s_initialized = false;
        static int s_array[256];
        if (!s_initialized)
        {
                InitializeDecodingLookupArray(s_array, s_vec, 64, false);
                s_initialized = true;
        }
        return s_array;
}


When thread 1 passes the if (!s_initialized) test, thread 2 has ample time 
to pass it as well and to concurrently initialize the array, before thread 
1 reaches s_initialized = true;.
A solution would be to use a mutex, which is a multiplatform issue unless 
CryptoPP gets compiled in C++11 (the language now has built-in mutexes).

Another solution would be to unconditionally initialize all those 
structures at library load time by using a singleton's constructor. 
Drawback is longer load time and memory use.

Yet another way would be to just make those structures compile-time static 
arrays, pre-computed in the source. Drawback is bigger binary, and usage of 
external script to pre-cook the sources.

There are are a few other suspect cases in the code:

$ grep static -r c5/*   | grep -n bool  | grep -v \(
15:c5/base32.cpp:       static volatile bool s_initialized = false;
20:c5/base64.cpp:       static volatile bool s_initialized = false;
68:c5/datatest.cpp:static bool s_thorough;
161:c5/gcm.h:   static volatile bool s_reductionTableInitialized;
186:c5/gost.h:          static volatile bool sTableCalculated;
190:c5/hex.cpp: static volatile bool s_initialized = false;
196:c5/hrtimer.cpp:     static bool getCurrentThreadImplemented = true;
205:c5/idea.h:          static volatile bool tablesBuilt;
338:c5/regtest.cpp:     static bool s_registered = false;
342:c5/rijndael.cpp:static volatile bool s_TeFilled = false, s_TdFilled = 
false;

Cheers,

Eric Cano

-- 
-- 
You received this message because you are subscribed to the "Crypto++ Users" 
Google Group.
To unsubscribe, send an email to [email protected].
More information about Crypto++ and this group is available at 
http://www.cryptopp.com.
--- 
You received this message because you are subscribed to the Google Groups 
"Crypto++ Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to