Patchwork [PING^2,C++] Add overflow checking to __cxa_vec_new[23]

login
register
mail settings
Submitter Florian Weimer
Date Nov. 2, 2012, 12:09 p.m.
Message ID <5093B7FC.30201@redhat.com>
Download mbox | patch
Permalink /patch/196549/
State New
Headers show

Comments

Florian Weimer - Nov. 2, 2012, 12:09 p.m.
On 10/30/2012 05:30 PM, Florian Weimer wrote:
> 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).

I looked at this again and made a new copy of the test case instead.  It 
has been successfully tested on x86_64-redhat-linux-gnu.

Is this okay for trunk?
Paolo Carlini - Nov. 2, 2012, 12:14 p.m.
On 11/02/2012 01:09 PM, Florian Weimer wrote:
> I looked at this again and made a new copy of the test case instead.  
> It has been successfully tested on x86_64-redhat-linux-gnu.
>
> Is this okay for trunk?
Looks very nice to me, and after all the issue seems rather simple. 
Let's say we wait another 2-3 days in case Jason and others have 
comments, and then it's Ok for mainline.

Thanks!
Paolo.

Patch

2012-11-02  Florian Weimer  <fweimer@redhat.com>

	* libsupc++/vec.cc (compute_size): New.
	(__cxa_vec_new2, __cxa_vec_new3): Use it.
	* testsuite/18_support/cxa_vec.cc: New.

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;
diff --git a/libstdc++-v3/testsuite/18_support/cxa_vec.cc b/libstdc++-v3/testsuite/18_support/cxa_vec.cc
new file mode 100644
index 0000000..5558f22
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/cxa_vec.cc
@@ -0,0 +1,64 @@ 
+// { dg-do run }
+// Avoid use of none-overridable new/delete operators in shared
+// { dg-options "-static" { target *-*-mingw* } }
+// Test __cxa_vec routines
+// Copyright (C) 2000-2012 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 7 Apr 2000 <nathan@nathan@codesourcery.com>
+
+#include <cxxabi.h>
+#include <stdio.h>
+#include <new>
+#include <stdlib.h>
+#include <setjmp.h>
+
+// Allocate enough padding to hold an array cookie.
+#ifdef __ARM_EABI__
+static const size_t padding = 8;
+#else
+static const size_t padding = (sizeof (std::size_t));
+#endif
+
+// our pseudo ctors and dtors
+static abi::__cxa_cdtor_return_type ctor (void *x)
+{
+  abort ();
+}
+
+static abi::__cxa_cdtor_return_type dtor (void *x)
+{
+  abort ();
+}
+
+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 addition
+void test1 ()
+{
+  try
+    {
+      abi::__cxa_vec_new (large_size, 4, padding, ctor, dtor);
+      abort ();
+    }
+  catch (std::bad_alloc &)
+    {
+    }
+}
+
+// allocate an array whose size causes an overflow during multiplication
+void test2 ()
+{
+  try
+    {
+      abi::__cxa_vec_new (std::size_t(-1) / 4, 4, padding, ctor, dtor);
+      abort ();
+    }
+  catch (std::bad_alloc &)
+    {
+    }
+}
+
+int main ()
+{
+  test1 ();
+  test2 ();
+}