Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception when using InitializeInteger with std::call_once #707

Closed
noloader opened this issue Aug 21, 2018 · 1 comment
Closed

Exception when using InitializeInteger with std::call_once #707

noloader opened this issue Aug 21, 2018 · 1 comment

Comments

@noloader
Copy link
Collaborator

noloader commented Aug 21, 2018

I'm seeing this exception on Linux and Solaris with newer GCC's. It happens on Linux with -DCRYPTOPP_INIT_PRIORITY=0, and it happens on Solaris 11 Sparc with GCC 7. Solaris does not have init priorities so we always use the std::call_once pattern when C++11 is available.

The reason we are seeing an exception in PKCS12_PBKDF is, it creates an Integer to help increment the buffer (IIRC).


Here is the relevant code for InitializeInteger. SetFunctionPointers just assigns a few function pointers for addition, subtraction, etc.

static void SetFunctionPointers();
InitializeInteger::InitializeInteger()
{
#if defined(CRYPTOPP_CXX11_SYNCHRONIZATION) && defined(CRYPTOPP_CXX11_DYNAMIC_INIT)
	static std::once_flag s_flag;
	std::call_once(s_flag, []() {
		SetFunctionPointers();
	});
#else
	static bool s_flag;
	MEMORY_BARRIER();
	if (s_flag == false)
	{
		SetFunctionPointers();
		s_flag = true;
		MEMORY_BARRIER();
	}
#endif // C++11 or C++03 flag
}

$ CXXFLAGS="-DNDEBUG -g2 -O0 -DCRYPTOPP_INIT_PRIORITY=0" make -j 4
...

$ gdb cryptest.exe
(gdb) catch throw
(gdb) r v
...

PKCS #12 PBKDF validation suite running...

Catchpoint 1 (exception thrown), 0x00007ffff7ad7181 in __cxxabiv1::__cxa_throw
    (obj=obj@entry=0xcc1260,
    tinfo=tinfo@entry=0x7ffff7dc9ae0 <typeinfo for std::system_error>,
    dest=dest@entry=0x7ffff7b03280 <std::system_error::~system_error()>)
    at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:78
78      in ../../../../libstdc++-v3/libsupc++/eh_throw.cc

(gdb) bt full
#0  0x00007ffff7ad7181 in __cxxabiv1::__cxa_throw (obj=obj@entry=0xcc1260,
    tinfo=tinfo@entry=0x7ffff7dc9ae0 <typeinfo for std::system_error>,
    dest=dest@entry=0x7ffff7b03280 <std::system_error::~system_error()>)
    at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:78
        globals = <optimized out>
        header = <optimized out>
#1  0x00007ffff7ad2c2d in std::__throw_system_error (__i=0xffffffff)
   from /lib64/libstdc++.so.6
No locals.
#2  0x00000000005b877d in std::call_once<CryptoPP::InitializeInteger::InitializeInteger()::<lambda()> >(std::once_flag &, CryptoPP::InitializeInteger::<lambda()> &&) (__once=..., __f=...) at /usr/include/c++/8/mutex:698
        __callable = {__(float) = @0x7fffffffbc9f}
        __e = 0xffffffff
#3  0x000000000059c709 in CryptoPP::InitializeInteger::InitializeInteger (
    this=0x7fffffffbd50) at integer.cpp:111
        s_flag = {_M_once = 0x0}
#4  0x00000000005affde in CryptoPP::Integer::Integer (this=0x7fffffffbd50,
    encodedInteger=0xcc1140 "\212\252\346){l\260FB\253[\axQ(N\267\022\217\032\212\252\346){l\260FB\253[\axQ(N\267\022\217\032\212\252\346){l\260FB\253[\axQ(N\267\022\217\032\212\252\346)", byteCount=0x40, s=CryptoPP::Integer::UNSIGNED,
    o=CryptoPP::BIG_ENDIAN_ORDER) at integer.cpp:3015
        block = <optimized out>
...
@noloader noloader added the Bug label Aug 21, 2018
noloader added a commit that referenced this issue Aug 21, 2018
This commit also favors init priorities over C++ dynamic initialization. After the std::call_once problems on Sparc and PowerPC I'm worried about problems with Dynamic Initialization and Destruction with Concurrency.
We also do away with supressing warnings and use CRYPTOPP_UNUSED instead.
@noloader
Copy link
Collaborator Author

The Linux exception is explained when failing to use -pthread. Also see GCC's Concurrency page.

I don't know what is happening on Solaris. Solaris is actually crashing with SIGSEGV. Also see Solaris 11 Sparc crash in std::call_once on the GCC Help mailing list.

It turns out that std::call_once is buggy due to bad interactions between libstdc++, glibc and pthreads. It is best to just avoid std::call_once because it is so buggy on so many platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant