Commit 52749b85df2e25c5ca35d5e0d07fbe4248b6f99b

Authored by Jay Berkenbilt
1 parent 619d294e

Make random data provider code thread-safe

This uses C++-11 thread-safe static initializers now.
Showing 1 changed file with 50 additions and 26 deletions
libqpdf/QUtil.cc
... ... @@ -878,57 +878,81 @@ QUtil::toUTF16(unsigned long uval)
878 878  
879 879 // Random data support
880 880  
881   -static RandomDataProvider* random_data_provider = 0;
  881 +class RandomDataProviderProvider
  882 +{
  883 + public:
  884 + RandomDataProviderProvider();
  885 + void setProvider(RandomDataProvider*);
  886 + RandomDataProvider* getProvider();
882 887  
  888 + private:
  889 + RandomDataProvider* default_provider;
  890 + RandomDataProvider* current_provider;
  891 +};
  892 +
  893 +RandomDataProviderProvider::RandomDataProviderProvider() :
  894 + default_provider(0),
  895 + current_provider(0)
  896 +{
883 897 #ifdef USE_INSECURE_RANDOM
884   -static RandomDataProvider* insecure_random_data_provider =
885   - InsecureRandomDataProvider::getInstance();
  898 + static RandomDataProvider* insecure_random_data_provider =
  899 + InsecureRandomDataProvider::getInstance();
886 900 #else
887   -static RandomDataProvider* insecure_random_data_provider = 0;
  901 + static RandomDataProvider* insecure_random_data_provider = 0;
888 902 #endif
889   -static RandomDataProvider* secure_random_data_provider =
890   - SecureRandomDataProvider::getInstance();
  903 + static RandomDataProvider* secure_random_data_provider =
  904 + SecureRandomDataProvider::getInstance();
  905 +
  906 + this->default_provider = (
  907 + secure_random_data_provider ? secure_random_data_provider
  908 + : insecure_random_data_provider ? insecure_random_data_provider
  909 + : 0);
891 910  
892   -static void
893   -initialize_random_data_provider()
894   -{
895   - if (random_data_provider == 0)
896   - {
897   - if (secure_random_data_provider)
898   - {
899   - random_data_provider = secure_random_data_provider;
900   - }
901   - else if (insecure_random_data_provider)
902   - {
903   - random_data_provider = insecure_random_data_provider;
904   - }
905   - }
906 911 // QUtil.hh has comments indicating that getRandomDataProvider(),
907 912 // which calls this method, never returns null.
908   - if (random_data_provider == 0)
  913 + if (this->default_provider == 0)
909 914 {
910 915 throw std::logic_error("QPDF has no random data provider");
911 916 }
  917 + this->current_provider = default_provider;
  918 +}
  919 +
  920 +RandomDataProvider*
  921 +RandomDataProviderProvider::getProvider()
  922 +{
  923 + return this->current_provider;
  924 +}
  925 +
  926 +void
  927 +RandomDataProviderProvider::setProvider(RandomDataProvider* p)
  928 +{
  929 + this->current_provider = p ? p : this->default_provider;
  930 +}
  931 +
  932 +static RandomDataProviderProvider*
  933 +getRandomDataProviderProvider()
  934 +{
  935 + // Thread-safe static initializer
  936 + static RandomDataProviderProvider rdpp;
  937 + return &rdpp;
912 938 }
913 939  
914 940 void
915 941 QUtil::setRandomDataProvider(RandomDataProvider* p)
916 942 {
917   - random_data_provider = p;
  943 + getRandomDataProviderProvider()->setProvider(p);
918 944 }
919 945  
920 946 RandomDataProvider*
921 947 QUtil::getRandomDataProvider()
922 948 {
923   - initialize_random_data_provider();
924   - return random_data_provider;
  949 + return getRandomDataProviderProvider()->getProvider();
925 950 }
926 951  
927 952 void
928 953 QUtil::initializeWithRandomBytes(unsigned char* data, size_t len)
929 954 {
930   - initialize_random_data_provider();
931   - random_data_provider->provideRandomData(data, len);
  955 + getRandomDataProvider()->provideRandomData(data, len);
932 956 }
933 957  
934 958 long
... ...