I have discovered that uClibc++ incorrectly implements C++ exception ABI, allocating not enough memory in the "__cxxabiv1::__cxa_allocate_exception": /// code begin /// retval = malloc (thrown_size + sizeof(__cxa_exception)); /// code end /// uClibc++ allocates "thrown_size + sizeof(__cxa_exception)" while stdlibc++ allocates "thrown_size += sizeof (__cxa_refcounted_exception);" since 2009-01-07 (https://gcc.gnu.org/bugzilla/attachment.cgi?id=17047) . The "__cxa_refcounted_exception" is wrapper around "__cxa_exception" and thus bigger than "__cxa_exception" alone. That causes memory corruption (buffer overflow) inside "__cxxabiv1::__cxa_throw" which is not implemented by uClibc++, but implemented by GCC's libsupc++: /// code begin (gcc-5.2.0/libstdc++-v3/libsupc++/eh_throw.cc:69) /// __cxa_refcounted_exception *header = __get_refcounted_exception_header_from_obj (obj); header->referenceCount = 1; /// code end /// In the code above, the "header->referenceCount = 1" writes in memory preceding region allocated for both thrown exception object and exception's structure. The "obj" is pointer to memory allocated by "__cxxabiv1::__cxa_allocate_exception", the "__get_refcounted_exception_header_from_obj (obj)" is defined as: /// code begin /// static inline __cxa_refcounted_exception * __get_refcounted_exception_header_from_obj (void *ptr) { return reinterpret_cast<__cxa_refcounted_exception *>(ptr) - 1; } /// code end /// Thus GCC's libsupc++ expects enough memory allocated preceding exception object to keep structure "__cxa_refcounted_exception", but uClibc++ allocates only "sizeof(__cxa_exception)" bytes before exception object. When binary is compiled for OpenWRT's musl libc standard library, the program crashes with SIGSEGV in the "free" call from "__cxxabiv1::__cxa_free_exception" because musl is very sensitive for memory corruption (musl's malloc stores meta-information about memory region in 8 bytes right before memory chunk itself). When compiled against glibc, the segmentation fault does not happen immediately in the "__cxxabiv1::__cxa_free_exception", but memory corruption still should take place, yielding undefined behavior. For your convenience, I have created OpenWRT package and feed for this test case: package: https://github.com/CoolSpot/openwrt-test/throw-catch-sigsegv feed: https://github.com/CoolSpot/openwrt-test-packages ### Installing the feed cd ~/Documents/openwrt echo "src-git openwrttest https://github.com/coolspot/openwrt-test-packages.git" >> ./feeds.conf ./scripts/feeds update openwrttest ./scripts/feeds install -a -p openwrttest ### Building the package make menuconfig # In the menuconfig select the package Test/sub-test/throw-catch-sigsegv to be built make package/throw-catch-sigsegv/install # Copy the package on the device (or VM) scp ./bin/malta/packages/openwrttest/throw-catch-sigsegv_2016-02-25_malta_mips.ipk qemu:/tmp/ # on the device (or VM) root@OpenWrt:~# opkg install /tmp/throw-catch-sigsegv_2016-02-25_malta_mips.ipk I am using following setup for reproducing: OpenWRT commit 4885087731e4ee9ac9823bd5cf3e777eecfd33d9 (Tue Feb 23 14:40:40 2016 +0000) I will provide proposed patch soon.
Created attachment 6376 [details] Proposed patch v1 Attached patch adds definition of the struct __cxa_refcounted_exception, functions __get_refcounted_exception_header_from_obj and __get_refcounted_exception_header_from_ue, changes functions __cxa_allocate_exception and __cxa_free_exception to allocate/free enough memory for __cxa_refcounted_exception instead of __cxa_exception.
2b58f77ee27c60842054fd0e5dd67f5d00e89eb8 some time ago should have fixed this.