From 9c5c4769a9c7a16aecc6cc7dd297bfe243dd022f Mon Sep 17 00:00:00 2001 From: weidai Date: Tue, 29 Jul 2003 01:18:33 +0000 Subject: [PATCH] fix potential threading problem with initialization of static objects --- dh.h | 2 +- ec2n.cpp | 3 +-- ecp.cpp | 3 +-- gf2n.cpp | 15 ++++++++---- hrtimer.cpp | 2 +- integer.cpp | 18 +++++++++----- misc.h | 42 ++++++++++++++++++++++++++------ nbtheory.cpp | 63 +++++++++++++++++++++++++++--------------------- polynomi.cpp | 6 ++--- polynomi.h | 68 +++++++++++++++++++++++++++++----------------------- pubkey.h | 12 +++++----- xtr.cpp | 5 ++-- xtr.h | 2 +- zinflate.cpp | 44 ++++++++++++++++------------------ zinflate.h | 4 ++-- 15 files changed, 169 insertions(+), 120 deletions(-) diff --git a/dh.h b/dh.h index 31fa7985..641d508b 100644 --- a/dh.h +++ b/dh.h @@ -78,7 +78,7 @@ public: private: const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const - {static KeyAgreementAlgorithm a; return a;} + {return Singleton().Ref();} DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;} diff --git a/ec2n.cpp b/ec2n.cpp index d668c4f0..946a9559 100644 --- a/ec2n.cpp +++ b/ec2n.cpp @@ -171,8 +171,7 @@ bool EC2N::Equal(const Point &P, const Point &Q) const const EC2N::Point& EC2N::Identity() const { - static const Point zero; - return zero; + return Singleton().Ref(); } const EC2N::Point& EC2N::Inverse(const Point &P) const diff --git a/ecp.cpp b/ecp.cpp index f13ee287..d8984387 100644 --- a/ecp.cpp +++ b/ecp.cpp @@ -195,8 +195,7 @@ bool ECP::Equal(const Point &P, const Point &Q) const const ECP::Point& ECP::Identity() const { - static const Point zero; - return zero; + return Singleton().Ref(); } const ECP::Point& ECP::Inverse(const Point &P) const diff --git a/gf2n.cpp b/gf2n.cpp index 93d5edeb..4f2b3e7d 100644 --- a/gf2n.cpp +++ b/gf2n.cpp @@ -111,16 +111,23 @@ PolynomialMod2 PolynomialMod2::Pentanomial(unsigned t0, unsigned t1, unsigned t2 return r; } +template +struct NewPolynomialMod2 +{ + PolynomialMod2 * operator()() const + { + return new PolynomialMod2(i); + } +}; + const PolynomialMod2 &PolynomialMod2::Zero() { - static const PolynomialMod2 zero; - return zero; + return Singleton().Ref(); } const PolynomialMod2 &PolynomialMod2::One() { - static const PolynomialMod2 one = 1; - return one; + return Singleton >().Ref(); } void PolynomialMod2::Decode(const byte *input, unsigned int inputLen) diff --git a/hrtimer.cpp b/hrtimer.cpp index 3396aea4..24fb6f93 100644 --- a/hrtimer.cpp +++ b/hrtimer.cpp @@ -40,7 +40,7 @@ word64 Timer::GetCurrentTimerValue() word64 Timer::TicksPerSecond() { #if defined(CRYPTOPP_WIN32_AVAILABLE) - static LARGE_INTEGER freq; + static LARGE_INTEGER freq = {0}; if (freq.QuadPart == 0) { if (!QueryPerformanceFrequency(&freq)) diff --git a/integer.cpp b/integer.cpp index dd667f99..f5b5fc47 100644 --- a/integer.cpp +++ b/integer.cpp @@ -2834,22 +2834,28 @@ Integer Integer::Power2(unsigned int e) return r; } +template +struct NewInteger +{ + Integer * operator()() const + { + return new Integer(i); + } +}; + const Integer &Integer::Zero() { - static const Integer zero; - return zero; + return Singleton().Ref(); } const Integer &Integer::One() { - static const Integer one(1,2); - return one; + return Singleton >().Ref(); } const Integer &Integer::Two() { - static const Integer two(2,2); - return two; + return Singleton >().Ref(); } bool Integer::operator!() const diff --git a/misc.h b/misc.h index 790e459b..659ba2a7 100644 --- a/misc.h +++ b/misc.h @@ -209,29 +209,57 @@ inline CipherDir GetCipherDir(const T &obj) return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION; } +template +struct NewObject +{ + T* operator()() const {return new T;} +}; + // This function safely initializes a static object in a multithreaded environment without using locks. // It may leak memory when two threads try to initialize the static object at the same time // but this should be acceptable since each static object is only initialized once per session. -template -T & StaticObject(F NewT, T *dummy=NULL) +template , int instance=0> +class Singleton { - static member_ptr s_pObject; +public: + Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} + + // VC60 workaround: use "..." to prevent this function from being inlined + const T & Ref(...) const; + +private: + F m_objectFactory; +}; + +template +const T & Singleton::Ref(...) const +{ + static simple_ptr s_pObject; static char s_objectState = 0; +retry: switch (s_objectState) { case 0: s_objectState = 1; - s_pObject.reset(NewT()); + try + { + s_pObject.m_p = m_objectFactory(); + } + catch(...) + { + s_objectState = 0; + throw; + } s_objectState = 2; break; case 1: - while (s_objectState == 1) {} + goto retry; default: break; } - return *s_pObject; -}; + return *s_pObject.m_p; +} // ************** rotate functions *************** diff --git a/nbtheory.cpp b/nbtheory.cpp index 013e4419..7d857fbf 100644 --- a/nbtheory.cpp +++ b/nbtheory.cpp @@ -15,36 +15,39 @@ NAMESPACE_BEGIN(CryptoPP) const word s_lastSmallPrime = 32719; -std::vector * NewPrimeTable() +struct NewPrimeTable { - const unsigned int maxPrimeTableSize = 3511; - - std::auto_ptr > pPrimeTable(new std::vector); - std::vector &primeTable = *pPrimeTable; - primeTable.reserve(maxPrimeTableSize); - - primeTable.push_back(2); - unsigned int testEntriesEnd = 1; - - for (unsigned int p=3; p<=s_lastSmallPrime; p+=2) + std::vector * operator()() const { - unsigned int j; - for (j=1; j > pPrimeTable(new std::vector); + std::vector &primeTable = *pPrimeTable; + primeTable.reserve(maxPrimeTableSize); + + primeTable.push_back(2); + unsigned int testEntriesEnd = 1; + + for (unsigned int p=3; p<=s_lastSmallPrime; p+=2) + { + unsigned int j; + for (j=1; j &primeTable = StaticObject >(&NewPrimeTable); + const std::vector &primeTable = Singleton, NewPrimeTable>().Ref(); size = primeTable.size(); return &primeTable[0]; } @@ -218,13 +221,19 @@ bool IsStrongLucasProbablePrime(const Integer &n) return false; } +struct NewLastSmallPrimeSquared +{ + Integer * operator()() const + { + return new Integer(Integer(s_lastSmallPrime).Squared()); + } +}; + bool IsPrime(const Integer &p) { - static const Integer lastSmallPrimeSquared = Integer(s_lastSmallPrime).Squared(); - if (p <= s_lastSmallPrime) return IsSmallPrime(p); - else if (p <= lastSmallPrimeSquared) + else if (p <= Singleton().Ref()) return SmallDivisorsTest(p); else return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p); diff --git a/polynomi.cpp b/polynomi.cpp index c049570b..be39bce4 100644 --- a/polynomi.cpp +++ b/polynomi.cpp @@ -565,15 +565,13 @@ Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const E template const PolynomialOverFixedRing &PolynomialOverFixedRing::Zero() { - static const PolynomialOverFixedRing zero; - return zero; + return Singleton().Ref(); } template const PolynomialOverFixedRing &PolynomialOverFixedRing::One() { - static const PolynomialOverFixedRing one = fixedRing.MultiplicativeIdentity(); - return one; + return Singleton().Ref(); } NAMESPACE_END diff --git a/polynomi.h b/polynomi.h index ce4295eb..f90c5136 100644 --- a/polynomi.h +++ b/polynomi.h @@ -170,7 +170,7 @@ public: //! \name CREATORS //@{ //! creates the zero polynomial - PolynomialOverFixedRing(unsigned int count = 0) : B(fixedRing, count) {} + PolynomialOverFixedRing(unsigned int count = 0) : B(ms_fixedRing, count) {} //! copy constructor PolynomialOverFixedRing(const ThisType &t) : B(t) {} @@ -185,7 +185,7 @@ public: : B(first, last) {} //! convert from string - explicit PolynomialOverFixedRing(const char *str) : B(str, fixedRing) {} + explicit PolynomialOverFixedRing(const char *str) : B(str, ms_fixedRing) {} //! convert from big-endian byte array PolynomialOverFixedRing(const byte *encodedPoly, unsigned int byteCount) : B(encodedPoly, byteCount) {} @@ -197,7 +197,7 @@ public: explicit PolynomialOverFixedRing(BufferedTransformation &bt) : B(bt) {} //! create a random PolynomialOverFixedRing - PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) : B(rng, parameter, fixedRing) {} + PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) : B(rng, parameter, ms_fixedRing) {} static const ThisType &Zero(); static const ThisType &One(); @@ -206,13 +206,13 @@ public: //! \name ACCESSORS //@{ //! the zero polynomial will return a degree of -1 - int Degree() const {return B::Degree(fixedRing);} + int Degree() const {return B::Degree(ms_fixedRing);} //! degree + 1 - unsigned int CoefficientCount() const {return B::CoefficientCount(fixedRing);} + unsigned int CoefficientCount() const {return B::CoefficientCount(ms_fixedRing);} //! return coefficient for x^i - CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, fixedRing);} + CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);} //! return coefficient for x^i - CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, fixedRing);} + CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);} //@} //! \name MANIPULATORS @@ -220,9 +220,9 @@ public: //! ThisType& operator=(const ThisType& t) {B::operator=(t); return *this;} //! - ThisType& operator+=(const ThisType& t) {Accumulate(t, fixedRing); return *this;} + ThisType& operator+=(const ThisType& t) {Accumulate(t, ms_fixedRing); return *this;} //! - ThisType& operator-=(const ThisType& t) {Reduce(t, fixedRing); return *this;} + ThisType& operator-=(const ThisType& t) {Reduce(t, ms_fixedRing); return *this;} //! ThisType& operator*=(const ThisType& t) {return *this = *this*t;} //! @@ -231,18 +231,18 @@ public: ThisType& operator%=(const ThisType& t) {return *this = *this%t;} //! - ThisType& operator<<=(unsigned int n) {ShiftLeft(n, fixedRing); return *this;} + ThisType& operator<<=(unsigned int n) {ShiftLeft(n, ms_fixedRing); return *this;} //! - ThisType& operator>>=(unsigned int n) {ShiftRight(n, fixedRing); return *this;} + ThisType& operator>>=(unsigned int n) {ShiftRight(n, ms_fixedRing); return *this;} //! set the coefficient for x^i to value - void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, fixedRing);} + void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, ms_fixedRing);} //! - void Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) {B::Randomize(rng, parameter, fixedRing);} + void Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) {B::Randomize(rng, parameter, ms_fixedRing);} //! - void Negate() {B::Negate(fixedRing);} + void Negate() {B::Negate(ms_fixedRing);} void swap(ThisType &t) {B::swap(t);} //@} @@ -254,7 +254,7 @@ public: //! ThisType operator+() const {return *this;} //! - ThisType operator-() const {return ThisType(Inverse(fixedRing));} + ThisType operator-() const {return ThisType(Inverse(ms_fixedRing));} //@} //! \name BINARY OPERATORS @@ -268,34 +268,42 @@ public: //! \name OTHER ARITHMETIC FUNCTIONS //@{ //! - ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(fixedRing));} + ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(ms_fixedRing));} //! - bool IsUnit() const {return B::IsUnit(fixedRing);} + bool IsUnit() const {return B::IsUnit(ms_fixedRing);} //! - ThisType Doubled() const {return ThisType(B::Doubled(fixedRing));} + ThisType Doubled() const {return ThisType(B::Doubled(ms_fixedRing));} //! - ThisType Squared() const {return ThisType(B::Squared(fixedRing));} + ThisType Squared() const {return ThisType(B::Squared(ms_fixedRing));} - CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, fixedRing);} + CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, ms_fixedRing);} //! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d)) static void Divide(ThisType &r, ThisType &q, const ThisType &a, const ThisType &d) - {B::Divide(r, q, a, d, fixedRing);} + {B::Divide(r, q, a, d, ms_fixedRing);} //@} //! \name INPUT/OUTPUT //@{ //! friend std::istream& operator>>(std::istream& in, ThisType &a) - {return a.Input(in, fixedRing);} + {return a.Input(in, ms_fixedRing);} //! friend std::ostream& operator<<(std::ostream& out, const ThisType &a) - {return a.Output(out, fixedRing);} + {return a.Output(out, ms_fixedRing);} //@} private: - static const Ring fixedRing; + struct NewOnePolynomial + { + ThisType * operator()() const + { + return new ThisType(ms_fixedRing.MultiplicativeIdentity()); + } + }; + + static const Ring ms_fixedRing; }; //! Ring of polynomials over another ring @@ -391,7 +399,7 @@ Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const E //! template inline bool operator==(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) - {return a.Equals(b, fixedRing);} + {return a.Equals(b, ms_fixedRing);} //! template inline bool operator!=(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) @@ -417,23 +425,23 @@ inline bool operator<=(const CryptoPP::PolynomialOverFixedRing &a, //! template inline CryptoPP::PolynomialOverFixedRing operator+(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) - {return CryptoPP::PolynomialOverFixedRing(a.Plus(b, fixedRing));} + {return CryptoPP::PolynomialOverFixedRing(a.Plus(b, ms_fixedRing));} //! template inline CryptoPP::PolynomialOverFixedRing operator-(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) - {return CryptoPP::PolynomialOverFixedRing(a.Minus(b, fixedRing));} + {return CryptoPP::PolynomialOverFixedRing(a.Minus(b, ms_fixedRing));} //! template inline CryptoPP::PolynomialOverFixedRing operator*(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) - {return CryptoPP::PolynomialOverFixedRing(a.Times(b, fixedRing));} + {return CryptoPP::PolynomialOverFixedRing(a.Times(b, ms_fixedRing));} //! template inline CryptoPP::PolynomialOverFixedRing operator/(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) - {return CryptoPP::PolynomialOverFixedRing(a.DividedBy(b, fixedRing));} + {return CryptoPP::PolynomialOverFixedRing(a.DividedBy(b, ms_fixedRing));} //! template inline CryptoPP::PolynomialOverFixedRing operator%(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) - {return CryptoPP::PolynomialOverFixedRing(a.Modulo(b, fixedRing));} + {return CryptoPP::PolynomialOverFixedRing(a.Modulo(b, ms_fixedRing));} NAMESPACE_END diff --git a/pubkey.h b/pubkey.h index fcf3f508..1b7f0473 100644 --- a/pubkey.h +++ b/pubkey.h @@ -414,7 +414,7 @@ public: protected: const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const - {static typename SCHEME_OPTIONS::MessageEncodingMethod messageEncodingMethod; return messageEncodingMethod;} + {return Singleton().Ref();} const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const {return GetKey();} const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const @@ -1322,17 +1322,17 @@ public: protected: const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const - {static typename SCHEME_OPTIONS::SignatureAlgorithm a; return a;} + {return Singleton().Ref();} const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const - {static typename SCHEME_OPTIONS::KeyAgreementAlgorithm a; return a;} + {return Singleton().Ref();} const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const - {static typename SCHEME_OPTIONS::KeyDerivationAlgorithm a; return a;} + {return Singleton().Ref();} const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const - {static typename SCHEME_OPTIONS::SymmetricEncryptionAlgorithm a; return a;} + {return Singleton().Ref();} HashIdentifier GetHashIdentifier() const {return HashIdentifier();} const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const - {static typename SCHEME_OPTIONS::MessageEncodingMethod a; return a;} + {return Singleton().Ref();} }; //! . diff --git a/xtr.cpp b/xtr.cpp index c0777319..cdb3fc82 100644 --- a/xtr.cpp +++ b/xtr.cpp @@ -8,10 +8,9 @@ NAMESPACE_BEGIN(CryptoPP) -GFP2Element & GFP2Element::Zero() +const GFP2Element & GFP2Element::Zero() { - static GFP2Element zero; - return zero; + return Singleton().Ref(); } void XTR_FindPrimesAndGenerator(RandomNumberGenerator &rng, Integer &p, Integer &q, GFP2Element &g, unsigned int pbits, unsigned int qbits) diff --git a/xtr.h b/xtr.h index 8f3ef278..89d39f03 100644 --- a/xtr.h +++ b/xtr.h @@ -33,7 +33,7 @@ public: c2.swap(a.c2); } - static GFP2Element & Zero(); + static const GFP2Element & Zero(); Integer c1, c2; }; diff --git a/zinflate.cpp b/zinflate.cpp index 3910c50f..4f5412c8 100644 --- a/zinflate.cpp +++ b/zinflate.cpp @@ -483,15 +483,15 @@ bool Inflator::DecodeBody() 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; - const HuffmanDecoder* pLiteralDecoder = GetLiteralDecoder(); - const HuffmanDecoder* pDistanceDecoder = GetDistanceDecoder(); + const HuffmanDecoder& literalDecoder = GetLiteralDecoder(); + const HuffmanDecoder& distanceDecoder = GetDistanceDecoder(); switch (m_nextDecode) { case LITERAL: while (true) { - if (!pLiteralDecoder->Decode(m_reader, m_literal)) + if (!literalDecoder.Decode(m_reader, m_literal)) { m_nextDecode = LITERAL; break; @@ -517,7 +517,7 @@ bool Inflator::DecodeBody() } m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257]; case DISTANCE: - if (!pDistanceDecoder->Decode(m_reader, m_distance)) + if (!distanceDecoder.Decode(m_reader, m_distance)) { m_nextDecode = DISTANCE; break; @@ -567,45 +567,41 @@ void Inflator::FlushOutput() } } -const HuffmanDecoder *Inflator::FixedLiteralDecoder() +struct NewFixedLiteralDecoder { - static simple_ptr s_pDecoder; - if (!s_pDecoder.m_p) + HuffmanDecoder * operator()() const { unsigned int codeLengths[288]; std::fill(codeLengths + 0, codeLengths + 144, 8); std::fill(codeLengths + 144, codeLengths + 256, 9); std::fill(codeLengths + 256, codeLengths + 280, 7); std::fill(codeLengths + 280, codeLengths + 288, 8); - HuffmanDecoder *pDecoder = new HuffmanDecoder; + std::auto_ptr pDecoder(new HuffmanDecoder); pDecoder->Initialize(codeLengths, 288); - s_pDecoder.m_p = pDecoder; + return pDecoder.release(); } - return s_pDecoder.m_p; -} +}; -const HuffmanDecoder *Inflator::FixedDistanceDecoder() +struct NewFixedDistanceDecoder { - static simple_ptr s_pDecoder; - if (!s_pDecoder.m_p) + HuffmanDecoder * operator()() const { unsigned int codeLengths[32]; std::fill(codeLengths + 0, codeLengths + 32, 5); - HuffmanDecoder *pDecoder = new HuffmanDecoder; + std::auto_ptr pDecoder(new HuffmanDecoder); pDecoder->Initialize(codeLengths, 32); - s_pDecoder.m_p = pDecoder; + return pDecoder.release(); } - return s_pDecoder.m_p; +}; + +const HuffmanDecoder& Inflator::GetLiteralDecoder() const +{ + return m_blockType == 1 ? Singleton().Ref() : m_dynamicLiteralDecoder; } -const HuffmanDecoder *Inflator::GetLiteralDecoder() const +const HuffmanDecoder& Inflator::GetDistanceDecoder() const { - return m_blockType == 1 ? FixedLiteralDecoder() : &m_dynamicLiteralDecoder; -} - -const HuffmanDecoder *Inflator::GetDistanceDecoder() const -{ - return m_blockType == 1 ? FixedDistanceDecoder() : &m_dynamicDistanceDecoder; + return m_blockType == 1 ? Singleton().Ref() : m_dynamicDistanceDecoder; } NAMESPACE_END diff --git a/zinflate.h b/zinflate.h index 34c39a8b..14829fde 100644 --- a/zinflate.h +++ b/zinflate.h @@ -127,8 +127,8 @@ private: static const HuffmanDecoder *FixedLiteralDecoder(); static const HuffmanDecoder *FixedDistanceDecoder(); - const HuffmanDecoder *GetLiteralDecoder() const; - const HuffmanDecoder *GetDistanceDecoder() const; + const HuffmanDecoder& GetLiteralDecoder() const; + const HuffmanDecoder& GetDistanceDecoder() const; enum State {PRE_STREAM, WAIT_HEADER, DECODING_BODY, POST_STREAM, AFTER_END}; State m_state;