Fix runtime crash when CRYPTOPP_INIT_PRIORITY=0
Couple use of initialization priorities to no NO_OS_DEPENDENCE Add comments explaining what integer does, how it does it, and why we want to inprove on the Singleton pattern as a resource manager. Update documentation.pull/398/head
parent
0e55f5ac7d
commit
c305e88127
5
config.h
5
config.h
|
|
@ -596,13 +596,14 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_USER_PRIORITY 350
|
# define CRYPTOPP_USER_PRIORITY 350
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (CRYPTOPP_INIT_PRIORITY > 0) && !(defined(__APPLE__) || defined(__sun__))
|
// Most platforms allow us to specify when to create C++ objects. Apple and Sun do not.
|
||||||
|
#if (CRYPTOPP_INIT_PRIORITY > 0) && !(defined(NO_OS_DEPENDENCE) || defined(__APPLE__) || defined(__sun__))
|
||||||
# if (CRYPTOPP_GCC_VERSION >= 30000) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (_INTEL_COMPILER >= 800)
|
# if (CRYPTOPP_GCC_VERSION >= 30000) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (_INTEL_COMPILER >= 800)
|
||||||
# define HAVE_GCC_INIT_PRIORITY 1
|
# define HAVE_GCC_INIT_PRIORITY 1
|
||||||
# elif (CRYPTOPP_MSC_VERSION >= 1310)
|
# elif (CRYPTOPP_MSC_VERSION >= 1310)
|
||||||
# define HAVE_MSC_INIT_PRIORITY 1
|
# define HAVE_MSC_INIT_PRIORITY 1
|
||||||
# endif
|
# endif
|
||||||
#endif // CRYPTOPP_INIT_PRIORITY, Sun, Darwin
|
#endif // CRYPTOPP_INIT_PRIORITY, NO_OS_DEPENDENCE, Apple, Sun
|
||||||
|
|
||||||
// ***************** determine availability of OS features ********************
|
// ***************** determine availability of OS features ********************
|
||||||
|
|
||||||
|
|
|
||||||
79
integer.cpp
79
integer.cpp
|
|
@ -1,6 +1,37 @@
|
||||||
// integer.cpp - originally written and placed in the public domain by Wei Dai
|
// integer.cpp - originally written and placed in the public domain by Wei Dai
|
||||||
// contains public domain code contributed by Alister Lee and Leonard Janke
|
// contains public domain code contributed by Alister Lee and Leonard Janke
|
||||||
|
|
||||||
|
// Notes by JW: The Integer class needs to do two things. First, it needs to set function
|
||||||
|
// pointers on some platforms, like X86 and X64. The function pointers select a fast multiply
|
||||||
|
// and addition based on the cpu. Second, it wants to create Integer::Zero(), Integer::One()
|
||||||
|
// and Integer::Two(). The function pointers are initialized in the class InitializeInteger.
|
||||||
|
// Wei's original code was much simpler. It uses the Singleton pattern, but it always produced
|
||||||
|
// memory findings. The Singleton generates memory findings because it used for a Create on
|
||||||
|
// First Use pattern. Resource destruction effectivley requires running resource acquisition
|
||||||
|
// with dependencies in reverse. For resources provided through the Singletons, there is no way
|
||||||
|
// to express the dependency order to safely destroy resources.
|
||||||
|
// The difference in the changes below is we use platform and language specific remediations
|
||||||
|
// if they are available. If not available, then we fall back to Wei's original code. If
|
||||||
|
// NO_OS_DEPENDENCE is defined, then the library uses Wei's original code.
|
||||||
|
// Under all versions of C++ on Linux and Microsoft platforms, we can use GCC's init_priority
|
||||||
|
// or MSVC's init_seg(lib) to initialize the function pointers and create the Integers 0, 1 and 2
|
||||||
|
// after CRT startup. This avoids the Singletons and clears over half the reports of memory
|
||||||
|
// leaks. However, it does not apply to Apple or Sun platforms.
|
||||||
|
// C++11 allows us to use call_once to set the function pointers, and Integer does so when
|
||||||
|
// init_priority and init_seg(lib) are not available. The class also uses the Singleton pattern
|
||||||
|
// to ensure integers 0, 1 and 2 are available. The Singleton will produce memory findings, but
|
||||||
|
// we don't have anything else to use in this case.
|
||||||
|
// C++03 on platforms like Apple and Sun, we use a boolean flag to track when the function pointers
|
||||||
|
// have been set based on the cpu. Its just a Nifty Counter in disguise, and its similar to using
|
||||||
|
// the g_pAssignToInteger to track initialization. It has concurrency issues, but a race is not a
|
||||||
|
// problem. It does not matter if two threads both set the same pointers. The Singleton pattern
|
||||||
|
// is also used to ensure integers 0, 1 and 2 are available. The Singleton will produce memory
|
||||||
|
// findings, but we don't have anything else to use in this case.
|
||||||
|
// While not readily apparent, Integer does not need to inherit from InitializeInteger when
|
||||||
|
// init_priority and init_seg(lib) are available. They just create an InitializePointers object
|
||||||
|
// at the right time after CRT initialization. The additional class avoids the small runtime
|
||||||
|
// overhead associated with checking the flags, and hides the detail from the interface.
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
|
@ -28,6 +59,7 @@
|
||||||
#include "smartptr.h"
|
#include "smartptr.h"
|
||||||
#include "algparam.h"
|
#include "algparam.h"
|
||||||
#include "filters.h"
|
#include "filters.h"
|
||||||
|
#include "stdcpp.h"
|
||||||
#include "asn.h"
|
#include "asn.h"
|
||||||
#include "oids.h"
|
#include "oids.h"
|
||||||
#include "words.h"
|
#include "words.h"
|
||||||
|
|
@ -73,11 +105,40 @@
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
static void SetFunctionPointers();
|
static void SetFunctionPointers();
|
||||||
|
#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY)
|
||||||
|
// Add InitializePointers to perform the work of setting pointers once.
|
||||||
|
struct InitializePointers
|
||||||
|
{
|
||||||
|
InitializePointers()
|
||||||
|
{
|
||||||
|
SetFunctionPointers();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Leave InitializeInteger empty so no work is done.
|
||||||
InitializeInteger::InitializeInteger()
|
InitializeInteger::InitializeInteger()
|
||||||
{
|
{
|
||||||
SetFunctionPointers();
|
|
||||||
}
|
}
|
||||||
|
#elif defined(CRYPTOPP_CXX11_SYNCHRONIZATION) && defined(CRYPTOPP_CXX11_DYNAMIC_INIT)
|
||||||
|
std::once_flag s_flag;
|
||||||
|
InitializeInteger::InitializeInteger()
|
||||||
|
{
|
||||||
|
std::call_once(s_flag, []() {
|
||||||
|
SetFunctionPointers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static bool s_flag;
|
||||||
|
InitializeInteger::InitializeInteger()
|
||||||
|
{
|
||||||
|
MEMORY_BARRIER();
|
||||||
|
if (s_flag == false)
|
||||||
|
{
|
||||||
|
SetFunctionPointers();
|
||||||
|
s_flag = true;
|
||||||
|
MEMORY_BARRIER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
template <long i>
|
template <long i>
|
||||||
struct NewInteger
|
struct NewInteger
|
||||||
{
|
{
|
||||||
|
|
@ -89,15 +150,15 @@ struct NewInteger
|
||||||
NAMESPACE_END
|
NAMESPACE_END
|
||||||
|
|
||||||
ANONYMOUS_NAMESPACE_BEGIN
|
ANONYMOUS_NAMESPACE_BEGIN
|
||||||
#if HAVE_GCC_INIT_PRIORITY
|
#if defined(HAVE_GCC_INIT_PRIORITY)
|
||||||
const CryptoPP::InitializeInteger s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 30))) = CryptoPP::InitializeInteger();
|
const CryptoPP::InitializePointers s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 30))) = CryptoPP::InitializePointers();
|
||||||
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 defined(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 CryptoPP::InitializeInteger s_init;
|
const CryptoPP::InitializePointers 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);
|
||||||
|
|
@ -3025,7 +3086,7 @@ Integer Integer::Power2(size_t e)
|
||||||
|
|
||||||
const Integer &Integer::Zero()
|
const Integer &Integer::Zero()
|
||||||
{
|
{
|
||||||
#if HAVE_GCC_INIT_PRIORITY || HAVE_MSC_INIT_PRIORITY
|
#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY)
|
||||||
return s_zero;
|
return s_zero;
|
||||||
#else
|
#else
|
||||||
return Singleton<Integer, NewInteger<0L> >().Ref();
|
return Singleton<Integer, NewInteger<0L> >().Ref();
|
||||||
|
|
@ -3034,7 +3095,7 @@ const Integer &Integer::Zero()
|
||||||
|
|
||||||
const Integer &Integer::One()
|
const Integer &Integer::One()
|
||||||
{
|
{
|
||||||
#if HAVE_GCC_INIT_PRIORITY || HAVE_MSC_INIT_PRIORITY
|
#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY)
|
||||||
return s_one;
|
return s_one;
|
||||||
#else
|
#else
|
||||||
return Singleton<Integer, NewInteger<1L> >().Ref();
|
return Singleton<Integer, NewInteger<1L> >().Ref();
|
||||||
|
|
@ -3043,7 +3104,7 @@ const Integer &Integer::One()
|
||||||
|
|
||||||
const Integer &Integer::Two()
|
const Integer &Integer::Two()
|
||||||
{
|
{
|
||||||
#if HAVE_GCC_INIT_PRIORITY || HAVE_MSC_INIT_PRIORITY
|
#if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY)
|
||||||
return s_two;
|
return s_two;
|
||||||
#else
|
#else
|
||||||
return Singleton<Integer, NewInteger<2L> >().Ref();
|
return Singleton<Integer, NewInteger<2L> >().Ref();
|
||||||
|
|
|
||||||
13
integer.h
13
integer.h
|
|
@ -8,6 +8,9 @@
|
||||||
//! has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
|
//! has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
|
||||||
//! used to hold the representation. The second is a Sign (an enumeration), and it is
|
//! used to hold the representation. The second is a Sign (an enumeration), and it is
|
||||||
//! used to track the sign of the Integer.
|
//! used to track the sign of the Integer.
|
||||||
|
//! \details For details on how the Integer class initializes its function pointers using
|
||||||
|
//! InitializeInteger and how it creates Integer::Zero(), Integer::One(), and
|
||||||
|
//! Integer::Two(), then see the comments at the top of <tt>integer.cpp</tt>.
|
||||||
//! \since Crypto++ 1.0
|
//! \since Crypto++ 1.0
|
||||||
|
|
||||||
#ifndef CRYPTOPP_INTEGER_H
|
#ifndef CRYPTOPP_INTEGER_H
|
||||||
|
|
@ -38,14 +41,12 @@ typedef SecBlock<word, AllocatorWithCleanup<word, true> > IntegerSecBlock;
|
||||||
//! has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
|
//! has two data members. The first is a IntegerSecBlock (a SecBlock<word>) and it is
|
||||||
//! used to hold the representation. The second is a Sign (an enumeration), and it is
|
//! used to hold the representation. The second is a Sign (an enumeration), and it is
|
||||||
//! used to track the sign of the Integer.
|
//! used to track the sign of the Integer.
|
||||||
|
//! \details For details on how the Integer class initializes its function pointers using
|
||||||
|
//! InitializeInteger and how it creates Integer::Zero(), Integer::One(), and
|
||||||
|
//! Integer::Two(), then see the comments at the top of <tt>integer.cpp</tt>.
|
||||||
//! \since Crypto++ 1.0
|
//! \since Crypto++ 1.0
|
||||||
//! \nosubgrouping
|
//! \nosubgrouping
|
||||||
class CRYPTOPP_DLL Integer
|
class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object
|
||||||
#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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue