Remove g_pAssignIntToInteger pointer, add CRYPTOPP_NO_ASSIGN_TO_INTEGER (Issue 389)

This effectively decouples Integer and Public Key from the rest of the library. The change means a compile time define is used rather than a runtime pointer. It avoids the race with Issue 389.
The Public Key algorithms will fail if you use them. For example, running the self tests with CRYPTOPP_NO_ASSIGN_TO_INTEGER in effect results in "CryptoPP::Exception caught: NameValuePairs: type mismatch for 'EquivalentTo', stored 'i', trying to retrieve 'N8CryptoPP7IntegerE'". The exception is expected, and the same happend when g_pAssignIntToInteger was present.
pull/398/head
Jeffrey Walton 2017-03-25 16:38:42 -04:00
parent 6c50a99254
commit 0e55f5ac7d
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
5 changed files with 54 additions and 36 deletions

View File

@ -9,8 +9,6 @@
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
PAssignIntToInteger g_pAssignIntToInteger = NULLPTR;
bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{ {
if (strcmp(name, "ValueNames") == 0) if (strcmp(name, "ValueNames") == 0)

View File

@ -298,9 +298,11 @@ AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &s
// ******************************************************** // ********************************************************
// to allow the linker to discard Integer code if not needed. #ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER
typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt); // Allow the linker to discard Integer code if not needed.
CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger; // Also see http://github.com/weidai11/cryptopp/issues/389.
bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt);
#endif
CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId(); CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
@ -386,8 +388,10 @@ public:
void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
{ {
// special case for retrieving an Integer parameter when an int was passed in #ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER
if (!(g_pAssignIntToInteger != NULLPTR && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value))) // Special case for retrieving an Integer parameter when an int was passed in
if (!(typeid(T) == typeid(int) && AssignIntToInteger(valueType, pValue, &m_value)))
#endif
{ {
NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType); NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
*reinterpret_cast<T *>(pValue) = m_value; *reinterpret_cast<T *>(pValue) = m_value;

View File

@ -103,6 +103,13 @@
// of 'b', 'o', 'h' or '.' (the last for decimal). // of 'b', 'o', 'h' or '.' (the last for decimal).
// #define CRYPTOPP_USE_STD_SHOWBASE // #define CRYPTOPP_USE_STD_SHOWBASE
// Define this if you want to decouple AlgorithmParameters and Integer
// The decoupling should make it easier for the linker to remove Integer
// related code for those who do not need Integer, and avoid a potential
// race during AssignIntToInteger pointer initialization. Also
// see http://github.com/weidai11/cryptopp/issues/389.
// #define CRYPTOPP_NO_ASSIGN_TO_INTEGER
// choose which style of sockets to wrap (mostly useful for MinGW which has both) // choose which style of sockets to wrap (mostly useful for MinGW which has both)
#if !defined(NO_BERKELEY_STYLE_SOCKETS) && !defined(PREFER_BERKELEY_STYLE_SOCKETS) #if !defined(NO_BERKELEY_STYLE_SOCKETS) && !defined(PREFER_BERKELEY_STYLE_SOCKETS)
# define PREFER_BERKELEY_STYLE_SOCKETS # define PREFER_BERKELEY_STYLE_SOCKETS

View File

@ -72,6 +72,12 @@
// ***************** C++ Static Initialization ******************** // ***************** C++ Static Initialization ********************
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
static void SetFunctionPointers();
InitializeInteger::InitializeInteger()
{
SetFunctionPointers();
}
template <long i> template <long i>
struct NewInteger struct NewInteger
{ {
@ -80,54 +86,28 @@ struct NewInteger
return new Integer(i); return new Integer(i);
} }
}; };
static void SetFunctionPointers();
bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt);
NAMESPACE_END NAMESPACE_END
ANONYMOUS_NAMESPACE_BEGIN ANONYMOUS_NAMESPACE_BEGIN
struct InitializeInteger
{
InitializeInteger()
{
CryptoPP::SetFunctionPointers();
CryptoPP::g_pAssignIntToInteger = (CryptoPP::PAssignIntToInteger)CryptoPP::AssignIntToInteger;
}
};
#if HAVE_GCC_INIT_PRIORITY #if HAVE_GCC_INIT_PRIORITY
const InitializeInteger s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 30))) = InitializeInteger(); const CryptoPP::InitializeInteger s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 30))) = CryptoPP::InitializeInteger();
const CryptoPP::Integer s_zero __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 31))) = CryptoPP::Integer(0L); const CryptoPP::Integer s_zero __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 31))) = CryptoPP::Integer(0L);
const CryptoPP::Integer s_one __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 32))) = CryptoPP::Integer(1L); const CryptoPP::Integer s_one __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 32))) = CryptoPP::Integer(1L);
const CryptoPP::Integer s_two __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 33))) = CryptoPP::Integer(2L); const CryptoPP::Integer s_two __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 33))) = CryptoPP::Integer(2L);
#elif HAVE_MSC_INIT_PRIORITY #elif HAVE_MSC_INIT_PRIORITY
#pragma warning(disable: 4075) #pragma warning(disable: 4075)
#pragma init_seg(".CRT$XCU-030") #pragma init_seg(".CRT$XCU-030")
const InitializeInteger s_init; const CryptoPP::InitializeInteger s_init;
const CryptoPP::Integer s_zero(0L); const CryptoPP::Integer s_zero(0L);
const CryptoPP::Integer s_one(1L); const CryptoPP::Integer s_one(1L);
const CryptoPP::Integer s_two(2L); const CryptoPP::Integer s_two(2L);
#pragma warning(default: 4075) #pragma warning(default: 4075)
#else
const InitializeInteger& s_init = CryptoPP::Singleton<InitializeInteger>().Ref();
const CryptoPP::Integer& s_zero = CryptoPP::Singleton<CryptoPP::Integer, CryptoPP::NewInteger<0L> >().Ref();
const CryptoPP::Integer& s_one = CryptoPP::Singleton<CryptoPP::Integer, CryptoPP::NewInteger<1L> >().Ref();
const CryptoPP::Integer& s_two = CryptoPP::Singleton<CryptoPP::Integer, CryptoPP::NewInteger<2L> >().Ref();
#endif #endif
ANONYMOUS_NAMESPACE_END ANONYMOUS_NAMESPACE_END
// ***************** Library code ******************** // ***************** Library code ********************
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt)
{
if (valueType != typeid(Integer))
return false;
*reinterpret_cast<Integer *>(pInteger) = *reinterpret_cast<const int *>(pInt);
return true;
}
inline static int Compare(const word *A, const word *B, size_t N) inline static int Compare(const word *A, const word *B, size_t N)
{ {
while (N--) while (N--)
@ -3045,17 +3025,29 @@ Integer Integer::Power2(size_t e)
const Integer &Integer::Zero() const Integer &Integer::Zero()
{ {
#if HAVE_GCC_INIT_PRIORITY || HAVE_MSC_INIT_PRIORITY
return s_zero; return s_zero;
#else
return Singleton<Integer, NewInteger<0L> >().Ref();
#endif
} }
const Integer &Integer::One() const Integer &Integer::One()
{ {
#if HAVE_GCC_INIT_PRIORITY || HAVE_MSC_INIT_PRIORITY
return s_one; return s_one;
#else
return Singleton<Integer, NewInteger<1L> >().Ref();
#endif
} }
const Integer &Integer::Two() const Integer &Integer::Two()
{ {
#if HAVE_GCC_INIT_PRIORITY || HAVE_MSC_INIT_PRIORITY
return s_two; return s_two;
#else
return Singleton<Integer, NewInteger<2L> >().Ref();
#endif
} }
bool Integer::operator!() const bool Integer::operator!() const
@ -4749,6 +4741,18 @@ std::string IntToString<word64>(word64 value, unsigned int base)
return result; return result;
} }
#ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER
// Allow the linker to discard Integer code if not needed.
// Also see http://github.com/weidai11/cryptopp/issues/389.
bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt)
{
if (valueType != typeid(Integer))
return false;
*reinterpret_cast<Integer *>(pInteger) = *reinterpret_cast<const int *>(pInt);
return true;
}
#endif
NAMESPACE_END NAMESPACE_END
#endif #endif

View File

@ -40,7 +40,12 @@ typedef SecBlock<word, AllocatorWithCleanup<word, true> > IntegerSecBlock;
//! used to track the sign of the Integer. //! used to track the sign of the Integer.
//! \since Crypto++ 1.0 //! \since Crypto++ 1.0
//! \nosubgrouping //! \nosubgrouping
class CRYPTOPP_DLL Integer : public ASN1Object class CRYPTOPP_DLL Integer
#if HAVE_GCC_INIT_PRIORITY || HAVE_MSC_INIT_PRIORITY
: private InitializeInteger, public ASN1Object
#else
: public ASN1Object
#endif
{ {
public: public:
//! \name ENUMS, EXCEPTIONS, and TYPEDEFS //! \name ENUMS, EXCEPTIONS, and TYPEDEFS