On Wednesday, December 10, 2014 6:25:21 AM UTC-5, Eric Cano wrote:
>
> 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.
>
The easiest solution may be to create a Base64{Encoder|Decoder} before the 
program switches to multiple threads. That way, there is no race during the 
lazy initialization.

I don't think its the best solution. Only the easiest.

Jeff

-- 
-- 
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