This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fortification of STL


Hi!

Several headers in libstdc++-v3 use __builtin_memmove, __builtin_memcpy
or __builtin_memset directly instead of making sure <string.h> is included
and using memmove/memcpy/memset.  I assume that's for header pollution
reasons.  Here is just what I found that could take advantage of the
protection, say std::copy, std::move or std::assign in a badly written
program could overflow a buffer and be catcheable either at compile time,
or at runtime.
The following patch of course is not meant to be directly used,
this should only be enabled if
1) _FORTIFY_SOURCE is defined
2) __OPTIMIZE__ > 0
3) we know the C library provides the checking functions (__memcpy_chk,
   __memmove_chk, __memset_chk in this case)
and having conditionals everywhere is jus too ugly to live with.
Guess some __gnu_* namespace could have an __attribute__((always_inline))
memcpy, memmove and memset routine that would either return
__builtin_* or __builtin___*_chk depending on preprocessor macros...

In the libstdc++-v3 testsuite no violations were reported at compile time
and only 3 tests called the __mem*_chk routines at runtime, but that of
course doesn't mean random C++ sources don't hit it much more often.

--- libstdc++-v3/include/bits/stl_algobase.h.jj	2007-08-13 15:11:18.000000000 +0200
+++ libstdc++-v3/include/bits/stl_algobase.h	2007-09-03 15:12:28.000000000 +0200
@@ -347,8 +347,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
         static _Tp*
         copy(const _Tp* __first, const _Tp* __last, _Tp* __result)
         { 
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	  __builtin___memmove_chk(__result, __first,
+				  sizeof(_Tp) * (__last - __first),
+				  __builtin_object_size (__result, 0));
+#else
 	  __builtin_memmove(__result, __first,
 			    sizeof(_Tp) * (__last - __first));
+#endif
 	  return __result + (__last - __first);
 	}
     };
@@ -464,7 +470,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
         __copy_b(const _Tp* __first, const _Tp* __last, _Tp* __result)
         { 
 	  const ptrdiff_t _Num = __last - __first;
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	  __builtin___memmove_chk(__result - _Num, __first,
+				  sizeof(_Tp) * _Num,
+				  __builtin_object_size (__result - _Num, 0));
+#else
 	  __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num);
+#endif
 	  return __result - _Num;
 	}
     };
@@ -560,17 +572,40 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   // Specialization: for char types we can use memset.
   inline void
   __fill_aux(unsigned char* __first, unsigned char* __last, unsigned char __c)
-  { __builtin_memset(__first, __c, __last - __first); }
+  {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+    __builtin___memset_chk(__first, __c, __last - __first,
+			   __builtin_object_size (__first, 0));
+#else
+    __builtin_memset(__first, __c, __last - __first);
+#endif
+  }
 
   inline void
   __fill_aux(signed char* __first, signed char* __last, signed char __c)
-  { __builtin_memset(__first, static_cast<unsigned char>(__c),
-		     __last - __first); }
+  {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+    __builtin___memset_chk(__first, static_cast<unsigned char>(__c),
+			   __last - __first,
+			   __builtin_object_size (__first, 0));
+#else
+    __builtin_memset(__first, static_cast<unsigned char>(__c),
+		     __last - __first);
+#endif
+  }
 
   inline void
   __fill_aux(char* __first, char* __last, char __c)
-  { __builtin_memset(__first, static_cast<unsigned char>(__c),
-		     __last - __first); }
+  {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+    __builtin___memset_chk(__first, static_cast<unsigned char>(__c),
+			   __last - __first,
+			   __builtin_object_size (__first, 0));
+#else
+    __builtin_memset(__first, static_cast<unsigned char>(__c),
+		     __last - __first);
+#endif
+  }
 
   /**
    *  @brief Fills the range [first,last) with copies of value.
--- libstdc++-v3/include/bits/char_traits.h.jj	2007-08-23 23:31:25.000000000 +0200
+++ libstdc++-v3/include/bits/char_traits.h	2007-09-03 14:29:47.000000000 +0200
@@ -187,6 +187,14 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     {
       return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
 						    __n * sizeof(char_type)));
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+      return static_cast<_CharT*>(__builtin___memmove_chk(__s1, __s2,
+							  __n * sizeof(char_type),
+							  __builtin_object_size (__s1, 0)));
+#else
+      return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
+						    __n * sizeof(char_type)));
+#endif
     }
 
   template<typename _CharT>
@@ -265,15 +273,35 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 
       static char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
-      { return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); }
+      {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+        return static_cast<char_type*>(__builtin___memmove_chk(__s1, __s2, __n,
+							       __builtin_object_size (__s1, 0)));
+#else
+        return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
+#endif
+      }
 
       static char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
-      { return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); }
+      {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+        return static_cast<char_type*>(__builtin___memcpy_chk(__s1, __s2, __n,
+							      __builtin_object_size (__s1, 0)));
+#else
+        return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
+#endif
+      }
 
       static char_type*
       assign(char_type* __s, size_t __n, char_type __a)
-      { return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); }
+      {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+        return static_cast<char_type*>(__builtin___memset_chk(__s, __a, __n, __builtin_object_size (__s, 0)));
+#else
+        return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
+#endif
+      }
 
       static char_type
       to_char_type(const int_type& __c)
--- libstdc++-v3/include/bits/valarray_array.h.jj	2007-05-21 16:35:00.000000000 +0200
+++ libstdc++-v3/include/bits/valarray_array.h	2007-09-03 14:32:58.000000000 +0200
@@ -91,7 +91,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       // For fundamental types, it suffices to say 'memset()'
       inline static void
       _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
-      { __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp)); }
+      {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	__builtin___memset_chk(__b, 0, (__e - __b) * sizeof(_Tp),
+			       __builtin_object_size (__b, 0));
+#else
+	__builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp));
+#endif
+      }
     };
 
   template<typename _Tp>
@@ -160,7 +167,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       inline static void
       _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
 	       _Tp* __restrict__ __o)
-      { __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp)); }
+      {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	__builtin___memcpy_chk(__o, __b, (__e - __b) * sizeof(_Tp),
+			       __builtin_object_size (__o, 0));
+#else
+	__builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp));
+#endif
+      }
     };
 
   template<typename _Tp>
@@ -267,7 +281,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
     {
       inline static void
       _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
-      { __builtin_memcpy(__b, __a, __n * sizeof (_Tp)); }
+      {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	__builtin___memcpy_chk(__b, __a, __n * sizeof(_Tp),
+			       __builtin_object_size (__b, 0));
+#else
+	__builtin_memcpy(__b, __a, __n * sizeof (_Tp));
+#endif
+      }
     };
 
   // Copy a plain array __a[<__n>] into a play array __b[<>]
--- libstdc++-v3/include/bits/locale_facets.h.jj	2007-05-21 16:35:00.000000000 +0200
+++ libstdc++-v3/include/bits/locale_facets.h	2007-09-03 14:30:11.000000000 +0200
@@ -899,7 +899,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       {
 	if (_M_widen_ok == 1)
 	  {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	    __builtin___memcpy_chk(__to, __lo, __hi - __lo, __builtin_object_size (__to, 0));
+#else
 	    __builtin_memcpy(__to, __lo, __hi - __lo);
+#endif
 	    return __hi;
 	  }
 	if (!_M_widen_ok)
@@ -964,7 +968,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       {
 	if (__builtin_expect(_M_narrow_ok == 1, true))
 	  {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	    __builtin___memcpy_chk(__to, __lo, __hi - __lo, __builtin_object_size (__to, 0));
+#else
 	    __builtin_memcpy(__to, __lo, __hi - __lo);
+#endif
 	    return __hi;
 	  }
 	if (!_M_narrow_ok)
@@ -1101,7 +1109,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       virtual const char*
       do_widen(const char* __lo, const char* __hi, char_type* __dest) const
       {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	__builtin___memcpy_chk(__dest, __lo, __hi - __lo, __builtin_object_size (__dest, 0));
+#else
 	__builtin_memcpy(__dest, __lo, __hi - __lo);
+#endif
 	return __hi;
       }
 
@@ -1154,7 +1166,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       do_narrow(const char_type* __lo, const char_type* __hi,
 		char, char* __dest) const
       {
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	__builtin___memcpy_chk(__dest, __lo, __hi - __lo, __builtin_object_size (__dest, 0));
+#else
 	__builtin_memcpy(__dest, __lo, __hi - __lo);
+#endif
 	return __hi;
       }
 
--- libstdc++-v3/include/ext/pod_char_traits.h.jj	2007-05-21 16:35:00.000000000 +0200
+++ libstdc++-v3/include/ext/pod_char_traits.h	2007-09-03 14:29:15.000000000 +0200
@@ -140,8 +140,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       static char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       { 
-	return static_cast<char_type*>
-	  (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)));
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+	return static_cast<char_type*>(__builtin___memmove_chk(__s1, __s2,
+							       __n * sizeof(char_type),
+							       __builtin_object_size (__s1, 0)));
+#else
+	return static_cast<char_type*>(__builtin_memmove(__s1, __s2,
+							 __n * sizeof(char_type)));
+#endif
       }
 
       static char_type*

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]