uclibc++: add a patch to fix memory corruption issues on exceptions
[openwrt/svn-archive/archive.git] / package / libs / uclibc++ / patches / 030-memory_corruption_fix.patch
diff --git a/package/libs/uclibc++/patches/030-memory_corruption_fix.patch b/package/libs/uclibc++/patches/030-memory_corruption_fix.patch
new file mode 100644 (file)
index 0000000..ba0d236
--- /dev/null
@@ -0,0 +1,114 @@
+From 1dc865b8bbb3911abc8ce53c7ae8a59dc90f6fc3 Mon Sep 17 00:00:00 2001
+From: Ivan Kold <pixus.ru@gmail.com>
+Date: Thu, 3 Mar 2016 12:56:30 -0800
+Subject: [PATCH] Fix throw statement causing memory corruption
+
+The __cxxabiv1::__cxa_throw in the GCC's libsupc++ expects
+sizeof(__cxa_refcounted_exception) bytes be allocated before
+exception object.
+uClibc++ allocates only sizeof(__cxa_exception) before an
+exception object.
+The __cxxabiv1::__cxa_throw writes in memory before allocated:
+// 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;
+
+Signed-off-by: Ivan Kold <pixus.ru@gmail.com>
+---
+ include/unwind-cxx.h | 34 +++++++++++++++++++++++++++++++++-
+ src/eh_alloc.cpp     |  8 ++++----
+ 2 files changed, 37 insertions(+), 5 deletions(-)
+
+--- a/include/unwind-cxx.h
++++ b/include/unwind-cxx.h
+@@ -1,5 +1,5 @@
+ // -*- C++ -*- Exception handling and frame unwind runtime interface routines.\r
+-// Copyright (C) 2001 Free Software Foundation, Inc.\r
++// Copyright (C) 2001-2015 Free Software Foundation, Inc.\r
+ //\r
+ // This file is part of GCC.\r
+ //\r
+@@ -13,6 +13,10 @@
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ // GNU General Public License for more details.\r
+ //\r
++// Under Section 7 of GPL version 3, you are granted additional\r
++// permissions described in the GCC Runtime Library Exception, version\r
++// 3.1, as published by the Free Software Foundation.\r
++//\r
+ // You should have received a copy of the GNU General Public License\r
+ // along with GCC; see the file COPYING.  If not, write to\r
+ // the Free Software Foundation, 59 Temple Place - Suite 330,\r
+@@ -40,6 +44,12 @@
+ #include <cstddef>\r
+ #include "unwind.h"\r
\r
++// Original unwind-cxx.h also includes bits/atomic_word.h which is CPU-specific, \r
++// but always defines _Atomic_word as typedef int .\r
++// Only thing that differs is memory-barrier macroses.\r
++typedef int _Atomic_word;\r
++\r
++\r
+ #pragma GCC visibility push(default)\r
\r
+ namespace __cxxabiv1\r
+@@ -79,6 +89,13 @@ struct __cxa_exception
+   _Unwind_Exception unwindHeader;\r
+ };\r
\r
++struct __cxa_refcounted_exception\r
++{\r
++  // Manage this header.\r
++  _Atomic_word referenceCount;\r
++  // __cxa_exception must be last, and no padding can be after it.\r
++  __cxa_exception exc;\r
++};\r
\r
+ // A dependent C++ exception object consists of a header, which is a wrapper\r
+ // around an unwind object header with additional C++ specific information,\r
+@@ -210,6 +227,21 @@ __get_exception_header_from_ue (_Unwind_
+   return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;\r
+ }\r
\r
++// Acquire the C++ refcounted exception header from the C++ object.\r
++static inline __cxa_refcounted_exception *\r
++__get_refcounted_exception_header_from_obj (void *ptr)\r
++{\r
++  return reinterpret_cast<__cxa_refcounted_exception *>(ptr) - 1;\r
++}\r
++\r
++// Acquire the C++ refcounted exception header from the generic exception\r
++// header.\r
++static inline __cxa_refcounted_exception *\r
++__get_refcounted_exception_header_from_ue (_Unwind_Exception *exc)\r
++{\r
++  return reinterpret_cast<__cxa_refcounted_exception *>(exc + 1) - 1;\r
++}\r
++\r
+ } /* namespace __cxxabiv1 */\r
\r
+ #pragma GCC visibility pop\r
+--- a/src/eh_alloc.cpp
++++ b/src/eh_alloc.cpp
+@@ -30,16 +30,16 @@ extern "C" void * __cxa_allocate_excepti
+       void *retval;
+       //The sizeof crap is required by Itanium ABI because we need to provide space for
+       //accounting information which is implementaion (gcc) specified
+-      retval = malloc (thrown_size + sizeof(__cxa_exception));
++      retval = malloc (thrown_size + sizeof(__cxa_refcounted_exception));
+       if (0 == retval){
+               std::terminate();
+       }
+-      memset (retval, 0, sizeof(__cxa_exception));
+-      return (void *)((unsigned char *)retval + sizeof(__cxa_exception));
++      memset (retval, 0, sizeof(__cxa_refcounted_exception));
++      return (void *)((unsigned char *)retval + sizeof(__cxa_refcounted_exception));
+ }
+ extern "C" void __cxa_free_exception(void *vptr) throw(){
+-      free( (char *)(vptr) - sizeof(__cxa_exception) );
++      free( (char *)(vptr) - sizeof(__cxa_refcounted_exception) );
+ }