diff options
author | rodrigo <rodrigo@FreeBSD.org> | 2016-06-01 04:07:21 +0800 |
---|---|---|
committer | rodrigo <rodrigo@FreeBSD.org> | 2016-06-01 04:07:21 +0800 |
commit | c6c5769b8325238610c26bae1e7a4fafca69d0c5 (patch) | |
tree | 982098fd577e4490c389763b914ad164b8250e1c /devel | |
parent | fe91d9fdb0757868c4403b899828bd4fad78a1c0 (diff) | |
download | freebsd-ports-gnome-c6c5769b8325238610c26bae1e7a4fafca69d0c5.tar.gz freebsd-ports-gnome-c6c5769b8325238610c26bae1e7a4fafca69d0c5.tar.zst freebsd-ports-gnome-c6c5769b8325238610c26bae1e7a4fafca69d0c5.zip |
Fix crash when libcxxrt exceptions been freed by a different language runtime,
and when libcxxrt itself free foreign exceptions.
Unwind API was specifically designed to allow mixed language environments where
exceptions from different runtimes interoperate. One particular example is
C++/LuaJit combination. Due to the issues in libcxxrt, databases/tarantool crashes
when linked against libcxxrt.
The issue was merged by upstream butat the moment not officially released.
https://github.com/pathscale/libcxxrt/pull/32
PR: 204786
Submitted by: Nick Zavaritsky <mejedi@gmail.com>
Approved by: Mahdi Mokhtari <mokhi64@gmail.com> (maintainer)
Diffstat (limited to 'devel')
-rw-r--r-- | devel/libcxxrt/Makefile | 3 | ||||
-rw-r--r-- | devel/libcxxrt/files/patch-src_exception.cc | 48 | ||||
-rw-r--r-- | devel/libcxxrt/files/patch-test_CMakeLists.txt | 24 | ||||
-rw-r--r-- | devel/libcxxrt/files/patch-test_test__foreign__exceptions.cc | 128 | ||||
-rw-r--r-- | devel/libcxxrt/pkg-descr | 2 |
5 files changed, 203 insertions, 2 deletions
diff --git a/devel/libcxxrt/Makefile b/devel/libcxxrt/Makefile index 81429375b9e7..7ef5077fdbcb 100644 --- a/devel/libcxxrt/Makefile +++ b/devel/libcxxrt/Makefile @@ -2,7 +2,7 @@ PORTNAME= libcxxrt PORTVERSION= 20131225 -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= devel MAINTAINER= mokhi64@gmail.com @@ -15,6 +15,7 @@ GH_ACCOUNT= pathscale GH_TAGNAME= 2f150a6 USES= cmake compiler:c++11-lang +USE_LDCONFIG= yes CXXFLAGS+= -nostdlib do-install: diff --git a/devel/libcxxrt/files/patch-src_exception.cc b/devel/libcxxrt/files/patch-src_exception.cc new file mode 100644 index 000000000000..2c4dfa5058c7 --- /dev/null +++ b/devel/libcxxrt/files/patch-src_exception.cc @@ -0,0 +1,48 @@ +--- src/exception.cc.orig 2013-12-26 03:11:27 UTC ++++ src/exception.cc +@@ -304,13 +304,17 @@ static pthread_key_t eh_key; + static void exception_cleanup(_Unwind_Reason_Code reason, + struct _Unwind_Exception *ex) + { +- __cxa_free_exception(static_cast<void*>(ex)); ++ // Exception layout: ++ // [__cxa_exception [_Unwind_Exception]] [exception object] ++ // ++ // __cxa_free_exception expects a pointer to the exception object ++ __cxa_free_exception(static_cast<void*>(ex + 1)); + } + static void dependent_exception_cleanup(_Unwind_Reason_Code reason, + struct _Unwind_Exception *ex) + { + +- __cxa_free_dependent_exception(static_cast<void*>(ex)); ++ __cxa_free_dependent_exception(static_cast<void*>(ex + 1)); + } + + /** +@@ -340,7 +344,8 @@ static void thread_cleanup(void* thread_ + if (info->foreign_exception_state != __cxa_thread_info::none) + { + _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(info->globals.caughtExceptions); +- e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); ++ if (e->exception_cleanup) ++ e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); + } + else + { +@@ -1270,12 +1275,13 @@ extern "C" void __cxa_end_catch() + + if (ti->foreign_exception_state != __cxa_thread_info::none) + { +- globals->caughtExceptions = 0; + if (ti->foreign_exception_state != __cxa_thread_info::rethrown) + { + _Unwind_Exception *e = reinterpret_cast<_Unwind_Exception*>(ti->globals.caughtExceptions); +- e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); ++ if (e->exception_cleanup) ++ e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e); + } ++ globals->caughtExceptions = 0; + ti->foreign_exception_state = __cxa_thread_info::none; + return; + } diff --git a/devel/libcxxrt/files/patch-test_CMakeLists.txt b/devel/libcxxrt/files/patch-test_CMakeLists.txt new file mode 100644 index 000000000000..11114df9d65a --- /dev/null +++ b/devel/libcxxrt/files/patch-test_CMakeLists.txt @@ -0,0 +1,24 @@ +--- test/CMakeLists.txt.orig 2013-12-26 03:11:27 UTC ++++ test/CMakeLists.txt +@@ -23,6 +23,11 @@ add_executable(cxxrt-test-shared ${CXXTE + set_property(TARGET cxxrt-test-shared PROPERTY LINK_FLAGS -nodefaultlibs) + target_link_libraries(cxxrt-test-shared cxxrt-shared pthread dl c) + ++include_directories(${CMAKE_SOURCE_DIR}/src) ++add_executable(cxxrt-test-foreign-exceptions test_foreign_exceptions.cc) ++set_property(TARGET cxxrt-test-foreign-exceptions PROPERTY LINK_FLAGS "-nodefaultlibs -Wl,--wrap,_Unwind_RaiseException") ++target_link_libraries(cxxrt-test-foreign-exceptions cxxrt-static gcc_s pthread dl c) ++ + add_test(cxxrt-test-static-test + ${CMAKE_CURRENT_SOURCE_DIR}/run_test.sh + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cxxrt-test-static +@@ -35,6 +40,9 @@ add_test(cxxrt-test-shared-test + ${CMAKE_CURRENT_BINARY_DIR}/expected_output.log + ${CMAKE_CURRENT_BINARY_DIR}/test-shared-output.log) + ++add_test(cxxrt-test-foreign-exceptions ++ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cxxrt-test-foreign-exceptions) ++ + set(valgrind "valgrind -q") + + if(TEST_VALGRIND) diff --git a/devel/libcxxrt/files/patch-test_test__foreign__exceptions.cc b/devel/libcxxrt/files/patch-test_test__foreign__exceptions.cc new file mode 100644 index 000000000000..baaaf2ee1bc4 --- /dev/null +++ b/devel/libcxxrt/files/patch-test_test__foreign__exceptions.cc @@ -0,0 +1,128 @@ +--- test/test_foreign_exceptions.cc.orig 2016-05-29 13:30:15 UTC ++++ test/test_foreign_exceptions.cc +@@ -0,0 +1,125 @@ ++#include <cstdio> ++#include <cstdlib> ++#include "unwind.h" ++ ++#define EXCEPTION_CLASS(a,b,c,d,e,f,g,h) \ ++ ((static_cast<uint64_t>(a) << 56) +\ ++ (static_cast<uint64_t>(b) << 48) +\ ++ (static_cast<uint64_t>(c) << 40) +\ ++ (static_cast<uint64_t>(d) << 32) +\ ++ (static_cast<uint64_t>(e) << 24) +\ ++ (static_cast<uint64_t>(f) << 16) +\ ++ (static_cast<uint64_t>(g) << 8) +\ ++ (static_cast<uint64_t>(h))) ++ ++// using ld --wrap=_Unwind_RaiseException hook feature ++extern "C" _Unwind_Reason_Code __real__Unwind_RaiseException (_Unwind_Exception *e); ++extern "C" _Unwind_Reason_Code __wrap__Unwind_RaiseException (_Unwind_Exception *e); ++ ++extern "C" _Unwind_Reason_Code __wrap__Unwind_RaiseException (_Unwind_Exception *e) ++{ ++ // clobber exception class forcing libcxx own exceptions to be treated ++ // as foreign exception within libcxx itself ++ e->exception_class = EXCEPTION_CLASS('F','O','R','E','I','G','N','\0'); ++ __real__Unwind_RaiseException(e); ++} ++ ++_Unwind_Exception global_e; ++ ++enum test_status { ++ PENDING, PASSED, FAILED ++}; ++ ++const char test_status_str[][8] = { ++ "PENDING", "PASSED", "FAILED" ++}; ++ ++test_status test1_status = PENDING; ++test_status test2_status = PENDING; ++test_status test3_status = PENDING; ++ ++void test2_exception_cleanup(_Unwind_Reason_Code code, _Unwind_Exception *e) ++{ ++ fputs("(2) exception_cleanup called\n", stderr); ++ if (e != &global_e) { ++ fprintf(stderr, "(2) ERROR: unexpected ptr: expecting %p, got %p\n", &global_e, e); ++ test2_status = FAILED; ++ } ++ if (test2_status == PENDING) ++ test2_status = PASSED; ++} ++ ++struct test3_exception ++{ ++ static int counter; ++ ~test3_exception() ++ { ++ counter++; ++ fputs("(3) exception dtor\n", stderr); ++ } ++}; ++int test3_exception::counter = 0; ++ ++int main() ++{ ++ /////////////////////////////////////////////////////////////// ++ fputs("(1) foreign exception, exception_cleanup=nullptr\n", stderr); ++ try ++ { ++ global_e.exception_class = 0; ++ global_e.exception_cleanup = 0; ++ __real__Unwind_RaiseException(&global_e); ++ } ++ catch (...) ++ { ++ } ++ test1_status = PASSED; ++ fputs("(1) PASS\n", stderr); ++ ++ /////////////////////////////////////////////////////////////// ++ fputs("(2) foreign exception, exception_cleanup present\n", stderr); ++ try ++ { ++ global_e.exception_class = 0; ++ global_e.exception_cleanup = test2_exception_cleanup; ++ __real__Unwind_RaiseException(&global_e); ++ } ++ catch (...) ++ { ++ } ++ fprintf(stderr, "(2) %s\n", test_status_str[test2_status]); ++ ++ /////////////////////////////////////////////////////////////// ++ fputs("(3) C++ exception in foreign environment\n", stderr); ++ int counter_expected; ++ try ++ { ++ // throw was rigged such that the runtime treats C++ exceptions ++ // as foreign ones ++ throw test3_exception(); ++ } ++ catch (test3_exception&) ++ { ++ fputs("(3) ERROR: wrong catch\n", stderr); ++ test3_status = FAILED; ++ } ++ catch (...) ++ { ++ fputs("(3) catch(...)\n", stderr); ++ counter_expected = test3_exception::counter + 1; ++ // one more dtor immediately after we leave catch ++ } ++ if (test3_status == PENDING && test3_exception::counter != counter_expected) { ++ fputs("(3) ERROR: exception dtor didn't run\n", stderr); ++ test3_status = FAILED; ++ } ++ if (test3_status == PENDING) ++ test3_status = PASSED; ++ fprintf(stderr, "(3) %s\n", test_status_str[test3_status]); ++ ++ /////////////////////////////////////////////////////////////// ++ if (test1_status == PASSED && test2_status == PASSED && test3_status == PASSED) ++ return EXIT_SUCCESS; ++ else ++ return EXIT_FAILURE; ++} diff --git a/devel/libcxxrt/pkg-descr b/devel/libcxxrt/pkg-descr index 5a746d4c11b5..7535b61f7890 100644 --- a/devel/libcxxrt/pkg-descr +++ b/devel/libcxxrt/pkg-descr @@ -1,6 +1,6 @@ This library implements the Code Sourcery C++ ABI, as documented here: -http://www.codesourcery.com/public/cxx-abi/abi.html +WWW: http://www.codesourcery.com/public/cxx-abi/abi.html It is intended to sit below an STL implementation, and provide features required by the compiler for implementation of the C++ language. |