diff mbox

[C++] Add overflow checking to __cxa_vec_new[23]

Message ID 503364F2.6020908@redhat.com
State New
Headers show

Commit Message

Florian Weimer Aug. 21, 2012, 10:37 a.m. UTC
I don't think there are any callers out there, but let's fix this for 
completeness.

A compiler emitting code to call this function would still have to 
perform overflow checks for the new T[n][m] case, so this interface is 
not as helpful as it looks at first glance.

Tested on x86_64-redhat-linux-gnu.

Comments

Florian Weimer Sept. 17, 2012, 9:51 a.m. UTC | #1
On 08/21/2012 12:37 PM, Florian Weimer wrote:
> I don't think there are any callers out there, but let's fix this for
> completeness.
>
> A compiler emitting code to call this function would still have to
> perform overflow checks for the new T[n][m] case, so this interface is
> not as helpful as it looks at first glance.
>
> Tested on x86_64-redhat-linux-gnu.

Ping?

This function is apparently used by compilers based on the EDG 
front-end, so it's not actually dead.
Paolo Carlini Sept. 17, 2012, 10:15 a.m. UTC | #2
Hi,

On 09/17/2012 11:51 AM, Florian Weimer wrote:
> On 08/21/2012 12:37 PM, Florian Weimer wrote:
>> I don't think there are any callers out there, but let's fix this for
>> completeness.
>>
>> A compiler emitting code to call this function would still have to
>> perform overflow checks for the new T[n][m] case, so this interface is
>> not as helpful as it looks at first glance.
>>
>> Tested on x86_64-redhat-linux-gnu.
>
> Ping?
>
> This function is apparently used by compilers based on the EDG 
> front-end, so it's not actually dead.
Being code that touches the library, the patch should go to the 
libstdc++ maliling list too. Likewise the testcase, should be in the 
libstdc++ testsuite, I guess.

That said, I didn't really follow the details of your recent work. Who 
did? Jason? I would gently ping the same maintainer.

Thanks!
Paolo.
Florian Weimer Sept. 17, 2012, 10:54 a.m. UTC | #3
On 09/17/2012 12:15 PM, Paolo Carlini wrote:
> Hi,
>
> On 09/17/2012 11:51 AM, Florian Weimer wrote:
>> On 08/21/2012 12:37 PM, Florian Weimer wrote:
>>> I don't think there are any callers out there, but let's fix this for
>>> completeness.
>>>
>>> A compiler emitting code to call this function would still have to
>>> perform overflow checks for the new T[n][m] case, so this interface is
>>> not as helpful as it looks at first glance.
>>>
>>> Tested on x86_64-redhat-linux-gnu.
>>
>> Ping?
>>
>> This function is apparently used by compilers based on the EDG
>> front-end, so it's not actually dead.

> Being code that touches the library, the patch should go to the
> libstdc++ maliling list too. Likewise the testcase, should be in the
> libstdc++ testsuite, I guess.

Oh, I thought that this wouldn't apply to internal C++ support code.  Sorry.

> That said, I didn't really follow the details of your recent work. Who
> did? Jason? I would gently ping the same maintainer.

Indeed, Jason reviewed that.  Cc:ing.
Florian Weimer Oct. 30, 2012, 4:01 p.m. UTC | #4
On 09/17/2012 12:54 PM, Florian Weimer wrote:
> On 09/17/2012 12:15 PM, Paolo Carlini wrote:
>> Hi,
>>
>> On 09/17/2012 11:51 AM, Florian Weimer wrote:
>>> On 08/21/2012 12:37 PM, Florian Weimer wrote:
>>>> I don't think there are any callers out there, but let's fix this for
>>>> completeness.
>>>>
>>>> A compiler emitting code to call this function would still have to
>>>> perform overflow checks for the new T[n][m] case, so this interface is
>>>> not as helpful as it looks at first glance.
>>>>
>>>> Tested on x86_64-redhat-linux-gnu.
>>>
>>> Ping?
>>>
>>> This function is apparently used by compilers based on the EDG
>>> front-end, so it's not actually dead.
>
>> Being code that touches the library, the patch should go to the
>> libstdc++ maliling list too. Likewise the testcase, should be in the
>> libstdc++ testsuite, I guess.
>
> Oh, I thought that this wouldn't apply to internal C++ support code.
> Sorry.
>
>> That said, I didn't really follow the details of your recent work. Who
>> did? Jason? I would gently ping the same maintainer.
>
> Indeed, Jason reviewed that.  Cc:ing.

Ping?

Patch is at: http://gcc.gnu.org/ml/gcc-patches/2012-08/msg01416.html

Thanks,
Florian
Paolo Carlini Oct. 30, 2012, 4:17 p.m. UTC | #5
Hi,

Florian Weimer <fweimer@redhat.com> ha scritto:

>Ping?
>
>Patch is at: http://gcc.gnu.org/ml/gcc-patches/2012-08/msg01416.html

Sorry, I don't know the code well enough to review your patch, but since I'm in CC, I still don't understand why, instead of adding a full libstdc++ testcase you are extending a C++ testcase, in old-deja even, normally considered legacy.

Paolo
Florian Weimer Oct. 30, 2012, 4:30 p.m. UTC | #6
On 10/30/2012 05:17 PM, Paolo Carlini wrote:

> Sorry, I don't know the code well enough to review your patch, but since I'm in CC, I still don't understand why, instead of adding a full libstdc++ testcase you are extending a C++ testcase, in old-deja even, normally considered legacy.

AFAIK, this is the only place we have such a test.  I suppose I could it 
put it into testsuite/18_support, but I would have to duplicate a bit of 
the machinery of the original test case because I can't just write a 
class and take the address of its constructor and destructor (whose 
addresses are passed to the tested functions).  I really didn't want to 
do that because there are some platform dependencies (the __ARM_EABI__ 
#ifdef).

Not sure if this makes sense, but those were my reasons.
diff mbox

Patch

2012-08-21  Florian Weimer  <fweimer@redhat.com>

	* libsupc++/vec.cc (compute_size): New function.
	(__cxa_vec_new2, __cxa_vec_new3): Use it.

2012-08-21  Florian Weimer  <fweimer@redhat.com>

	* g++.old-deja/g++.abi/cxa_vec.C (test5, test6): New.

diff --git a/gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C b/gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C
index f3d602f..e2b82e7 100644
--- a/gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C
+++ b/gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C
@@ -8,7 +8,7 @@ 
 // Avoid use of none-overridable new/delete operators in shared
 // { dg-options "-static" { target *-*-mingw* } }
 // Test __cxa_vec routines
-// Copyright (C) 2000, 2005 Free Software Foundation, Inc.
+// Copyright (C) 2000-2012 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 7 Apr 2000 <nathan@nathan@codesourcery.com>
 
 #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
@@ -255,6 +255,80 @@  void test4 ()
   return;
 }
 
+static const std::size_t large_size = std::size_t(1) << (sizeof(std::size_t) * 8 - 2);
+
+// allocate an array whose size causes an overflow during multiplication
+void test5 ()
+{
+  static bool started = false;
+
+  if (!started)
+    {
+      started = true;
+      std::set_terminate (test0);
+
+      ctor_count = dtor_count = 1;
+      dtor_repeat = false;
+      blocks = 0;
+
+      try
+        {
+          void *ary = abi::__cxa_vec_new (large_size, 4, padding, ctor, dtor);
+	  longjmp (jump, 1);
+        }
+      catch (std::bad_alloc)
+	{
+	  if (ctor_count != 1)
+	    longjmp (jump, 4);
+	}
+      catch (...)
+        {
+          longjmp (jump, 2);
+        }
+    }
+  else
+    {
+      longjmp (jump, 3);
+    }
+  return;
+}
+
+// allocate an array whose size causes an overflow during addition
+void test6 ()
+{
+  static bool started = false;
+
+  if (!started)
+    {
+      started = true;
+      std::set_terminate (test0);
+
+      ctor_count = dtor_count = 1;
+      dtor_repeat = false;
+      blocks = 0;
+
+      try
+        {
+          void *ary = abi::__cxa_vec_new (std::size_t(-1) / 4, 4, padding, ctor, dtor);
+	  longjmp (jump, 1);
+        }
+      catch (std::bad_alloc)
+	{
+	  if (ctor_count != 1)
+	    longjmp (jump, 4);
+	}
+      catch (...)
+        {
+          longjmp (jump, 2);
+        }
+    }
+  else
+    {
+      longjmp (jump, 3);
+    }
+  return;
+}
+
 static void (*tests[])() =
 {
   test0,
@@ -262,6 +336,8 @@  static void (*tests[])() =
   test2,
   test3,
   test4,
+  test5,
+  test6,
   NULL
 };
 
diff --git a/libstdc++-v3/libsupc++/vec.cc b/libstdc++-v3/libsupc++/vec.cc
index 700c5ef..bfce117 100644
--- a/libstdc++-v3/libsupc++/vec.cc
+++ b/libstdc++-v3/libsupc++/vec.cc
@@ -1,6 +1,6 @@ 
 // New abi Support -*- C++ -*-
 
-// Copyright (C) 2000, 2001, 2003, 2004, 2009, 2011
+// Copyright (C) 2000-2012
 // Free Software Foundation, Inc.
 //  
 // This file is part of GCC.
@@ -59,6 +59,19 @@  namespace __cxxabiv1
       globals->caughtExceptions = p->nextException;
       globals->uncaughtExceptions += 1;
     }
+
+    // Compute the total size with overflow checking.
+    std::size_t compute_size(std::size_t element_count,
+			     std::size_t element_size,
+			     std::size_t padding_size)
+    {
+      if (element_size && element_count > std::size_t(-1) / element_size)
+	throw std::bad_alloc();
+      std::size_t size = element_count * element_size;
+      if (size + padding_size < size)
+	throw std::bad_alloc();
+      return size + padding_size;
+    }
   }
 
   // Allocate and construct array.
@@ -83,7 +96,8 @@  namespace __cxxabiv1
 		 void *(*alloc) (std::size_t),
 		 void (*dealloc) (void *))
   {
-    std::size_t size = element_count * element_size + padding_size;
+    std::size_t size
+      = compute_size(element_count, element_size, padding_size);
     char *base = static_cast <char *> (alloc (size));
     if (!base)
       return base;
@@ -124,7 +138,8 @@  namespace __cxxabiv1
 		 void *(*alloc) (std::size_t),
 		 void (*dealloc) (void *, std::size_t))
   {
-    std::size_t size = element_count * element_size + padding_size;
+    std::size_t size
+      = compute_size(element_count, element_size, padding_size);
     char *base = static_cast<char *>(alloc (size));
     if (!base)
       return base;