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 ¶meters) {}
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.