Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 606350 Details for
Bug 850911
g++: operator new[] overflow fix
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
operator-new.patch
operator-new.patch (text/plain), 20.83 KB, created by
Florian Weimer
on 2012-08-22 17:13:42 UTC
(
hide
)
Description:
operator-new.patch
Filename:
MIME Type:
Creator:
Florian Weimer
Created:
2012-08-22 17:13:42 UTC
Size:
20.83 KB
patch
obsolete
>Backport operator new[] overflow fix: > >http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19351 >http://gcc.gnu.org/viewcvs?view=revision&revision=190546 >http://gcc.gnu.org/viewcvs?view=revision&revision=188948 > >diff --git a/gcc-4.7.1-20120813/gcc/cp/call.c b/gcc-4.7.1-20120813/gcc/cp/call.c >index 5e74f56..7eb751c 100644 >--- a/gcc-4.7.1-20120813/gcc/cp/call.c >+++ b/gcc-4.7.1-20120813/gcc/cp/call.c >@@ -3906,15 +3906,19 @@ build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p, > total number of bytes required by the allocation, and is updated if > that is changed here. *COOKIE_SIZE is non-NULL if a cookie should > be used. If this function determines that no cookie should be >- used, after all, *COOKIE_SIZE is set to NULL_TREE. If FN is >- non-NULL, it will be set, upon return, to the allocation function >- called. */ >+ used, after all, *COOKIE_SIZE is set to NULL_TREE. If SIZE_CHECK >+ is not NULL_TREE, it is evaluated before calculating the final >+ array size, and if it fails, the array size is replaced with >+ (size_t)-1 (usually triggering a std::bad_alloc exception). If FN >+ is non-NULL, it will be set, upon return, to the allocation >+ function called. */ > > tree > build_operator_new_call (tree fnname, VEC(tree,gc) **args, >- tree *size, tree *cookie_size, >+ tree *size, tree *cookie_size, tree size_check, > tree *fn) > { >+ tree original_size = *size; > tree fns; > struct z_candidate *candidates; > struct z_candidate *cand; >@@ -3922,6 +3926,10 @@ build_operator_new_call (tree fnname, VEC(tree,gc) **args, > > if (fn) > *fn = NULL_TREE; >+ /* Set to (size_t)-1 if the size check fails. */ >+ if (size_check != NULL_TREE) >+ *size = fold_build3 (COND_EXPR, sizetype, size_check, >+ original_size, TYPE_MAX_VALUE (sizetype)); > VEC_safe_insert (tree, gc, *args, 0, *size); > *args = resolve_args (*args, tf_warning_or_error); > if (*args == NULL) >@@ -3983,7 +3991,11 @@ build_operator_new_call (tree fnname, VEC(tree,gc) **args, > if (use_cookie) > { > /* Update the total size. */ >- *size = size_binop (PLUS_EXPR, *size, *cookie_size); >+ *size = size_binop (PLUS_EXPR, original_size, *cookie_size); >+ /* Set to (size_t)-1 if the size check fails. */ >+ gcc_assert (size_check != NULL_TREE); >+ *size = fold_build3 (COND_EXPR, sizetype, size_check, >+ *size, TYPE_MAX_VALUE (sizetype)); > /* Update the argument list to reflect the adjusted size. */ > VEC_replace (tree, *args, 0, *size); > } >diff --git a/gcc-4.7.1-20120813/gcc/cp/cp-tree.h b/gcc-4.7.1-20120813/gcc/cp/cp-tree.h >index 4b3c77d..a43a2e5 100644 >--- a/gcc-4.7.1-20120813/gcc/cp/cp-tree.h >+++ b/gcc-4.7.1-20120813/gcc/cp/cp-tree.h >@@ -4863,7 +4863,7 @@ extern tree build_user_type_conversion (tree, tree, int); > extern tree build_new_function_call (tree, VEC(tree,gc) **, bool, > tsubst_flags_t); > extern tree build_operator_new_call (tree, VEC(tree,gc) **, tree *, >- tree *, tree *); >+ tree *, tree, tree *); > extern tree build_new_method_call (tree, tree, VEC(tree,gc) **, > tree, int, tree *, > tsubst_flags_t); >diff --git a/gcc-4.7.1-20120813/gcc/cp/init.c b/gcc-4.7.1-20120813/gcc/cp/init.c >index 2829c28..7920f11 100644 >--- a/gcc-4.7.1-20120813/gcc/cp/init.c >+++ b/gcc-4.7.1-20120813/gcc/cp/init.c >@@ -2169,6 +2169,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, > tree pointer_type; > tree non_const_pointer_type; > tree outer_nelts = NULL_TREE; >+ /* For arrays, a bounds checks on the NELTS parameter. */ >+ tree outer_nelts_check = NULL_TREE; >+ bool outer_nelts_from_type = false; >+ double_int inner_nelts_count = double_int_one; > tree alloc_call, alloc_expr; > /* The address returned by the call to "operator new". This node is > a VAR_DECL and is therefore reusable. */ >@@ -2203,10 +2207,14 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, > } > else if (TREE_CODE (type) == ARRAY_TYPE) > { >+ /* Transforms new (T[N]) to new T[N]. The former is a GNU >+ extension for variable N. (This also covers new T where T is >+ a VLA typedef.) */ > array_p = true; > nelts = array_type_nelts_top (type); > outer_nelts = nelts; > type = TREE_TYPE (type); >+ outer_nelts_from_type = true; > } > > /* If our base type is an array, then make sure we know how many elements >@@ -2214,10 +2222,61 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, > for (elt_type = type; > TREE_CODE (elt_type) == ARRAY_TYPE; > elt_type = TREE_TYPE (elt_type)) >- nelts = cp_build_binary_op (input_location, >- MULT_EXPR, nelts, >- array_type_nelts_top (elt_type), >- complain); >+ { >+ tree inner_nelts = array_type_nelts_top (elt_type); >+ tree inner_nelts_cst = maybe_constant_value (inner_nelts); >+ if (TREE_CONSTANT (inner_nelts_cst) >+ && TREE_CODE (inner_nelts_cst) == INTEGER_CST) >+ { >+ double_int result; >+ if (mul_double (TREE_INT_CST_LOW (inner_nelts_cst), >+ TREE_INT_CST_HIGH (inner_nelts_cst), >+ inner_nelts_count.low, inner_nelts_count.high, >+ &result.low, &result.high)) >+ { >+ if (complain & tf_error) >+ error ("integer overflow in array size"); >+ nelts = error_mark_node; >+ } >+ inner_nelts_count = result; >+ } >+ else >+ { >+ if (complain & tf_error) >+ { >+ error_at (EXPR_LOC_OR_HERE (inner_nelts), >+ "array size in operator new must be constant"); >+ cxx_constant_value(inner_nelts); >+ } >+ nelts = error_mark_node; >+ } >+ if (nelts != error_mark_node) >+ nelts = cp_build_binary_op (input_location, >+ MULT_EXPR, nelts, >+ inner_nelts_cst, >+ complain); >+ } >+ >+ if (variably_modified_type_p (elt_type, NULL_TREE) && (complain & tf_error)) >+ { >+ error ("variably modified type not allowed in operator new"); >+ return error_mark_node; >+ } >+ >+ if (nelts == error_mark_node) >+ return error_mark_node; >+ >+ /* Warn if we performed the (T[N]) to T[N] transformation and N is >+ variable. */ >+ if (outer_nelts_from_type >+ && !TREE_CONSTANT (maybe_constant_value (outer_nelts))) >+ { >+ if (complain & tf_warning_or_error) >+ pedwarn(EXPR_LOC_OR_HERE (outer_nelts), OPT_Wvla, >+ "ISO C++ does not support variable-length array types"); >+ else >+ return error_mark_node; >+ } > > if (TREE_CODE (elt_type) == VOID_TYPE) > { >@@ -2271,7 +2330,56 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, > > size = size_in_bytes (elt_type); > if (array_p) >- size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); >+ { >+ /* Maximum available size in bytes. Half of the address space >+ minus the cookie size. */ >+ double_int max_size >+ = double_int_lshift (double_int_one, TYPE_PRECISION (sizetype) - 1, >+ HOST_BITS_PER_DOUBLE_INT, false); >+ /* Size of the inner array elements. */ >+ double_int inner_size; >+ /* Maximum number of outer elements which can be allocated. */ >+ double_int max_outer_nelts; >+ tree max_outer_nelts_tree; >+ >+ gcc_assert (TREE_CODE (size) == INTEGER_CST); >+ cookie_size = targetm.cxx.get_cookie_size (elt_type); >+ gcc_assert (TREE_CODE (cookie_size) == INTEGER_CST); >+ gcc_checking_assert (double_int_ucmp >+ (TREE_INT_CST (cookie_size), max_size) < 0); >+ /* Unconditionally substract the cookie size. This decreases the >+ maximum object size and is safe even if we choose not to use >+ a cookie after all. */ >+ max_size = double_int_sub (max_size, TREE_INT_CST (cookie_size)); >+ if (mul_double (TREE_INT_CST_LOW (size), TREE_INT_CST_HIGH (size), >+ inner_nelts_count.low, inner_nelts_count.high, >+ &inner_size.low, &inner_size.high) >+ || double_int_ucmp (inner_size, max_size) > 0) >+ { >+ if (complain & tf_error) >+ error ("size of array is too large"); >+ return error_mark_node; >+ } >+ max_outer_nelts = double_int_udiv (max_size, inner_size, TRUNC_DIV_EXPR); >+ /* Only keep the top-most seven bits, to simplify encoding the >+ constant in the instruction stream. */ >+ { >+ unsigned shift = HOST_BITS_PER_DOUBLE_INT - 7 >+ - (max_outer_nelts.high ? clz_hwi (max_outer_nelts.high) >+ : (HOST_BITS_PER_WIDE_INT + clz_hwi (max_outer_nelts.low))); >+ max_outer_nelts >+ = double_int_lshift (double_int_rshift >+ (max_outer_nelts, shift, >+ HOST_BITS_PER_DOUBLE_INT, false), >+ shift, HOST_BITS_PER_DOUBLE_INT, false); >+ } >+ max_outer_nelts_tree = double_int_to_tree (sizetype, max_outer_nelts); >+ >+ size = size_binop (MULT_EXPR, size, convert (sizetype, nelts)); >+ outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node, >+ outer_nelts, >+ max_outer_nelts_tree); >+ } > > alloc_fn = NULL_TREE; > >@@ -2334,10 +2442,13 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, > /* Use a class-specific operator new. */ > /* If a cookie is required, add some extra space. */ > if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)) >- { >- cookie_size = targetm.cxx.get_cookie_size (elt_type); >- size = size_binop (PLUS_EXPR, size, cookie_size); >- } >+ size = size_binop (PLUS_EXPR, size, cookie_size); >+ else >+ cookie_size = NULL_TREE; >+ /* Perform the overflow check. */ >+ if (outer_nelts_check != NULL_TREE) >+ size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check, >+ size, TYPE_MAX_VALUE (sizetype)); > /* Create the argument list. */ > VEC_safe_insert (tree, gc, *placement, 0, size); > /* Do name-lookup to find the appropriate operator. */ >@@ -2368,13 +2479,12 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, > { > /* Use a global operator new. */ > /* See if a cookie might be required. */ >- if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type)) >- cookie_size = targetm.cxx.get_cookie_size (elt_type); >- else >+ if (!(array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))) > cookie_size = NULL_TREE; > > alloc_call = build_operator_new_call (fnname, placement, > &size, &cookie_size, >+ outer_nelts_check, > &alloc_fn); > } > } >diff --git a/gcc-4.7.1-20120813/gcc/cp/parser.c b/gcc-4.7.1-20120813/gcc/cp/parser.c >index a7018d4..c01f22b 100644 >--- a/gcc-4.7.1-20120813/gcc/cp/parser.c >+++ b/gcc-4.7.1-20120813/gcc/cp/parser.c >@@ -6878,41 +6878,34 @@ cp_parser_direct_new_declarator (cp_parser* parser) > while (true) > { > tree expression; >+ cp_token *token; > > /* Look for the opening `['. */ > cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE); >- /* The first expression is not required to be constant. */ >- if (!declarator) >+ >+ token = cp_lexer_peek_token (parser->lexer); >+ expression = cp_parser_expression (parser, /*cast_p=*/false, NULL); >+ /* The standard requires that the expression have integral >+ type. DR 74 adds enumeration types. We believe that the >+ real intent is that these expressions be handled like the >+ expression in a `switch' condition, which also allows >+ classes with a single conversion to integral or >+ enumeration type. */ >+ if (!processing_template_decl) > { >- cp_token *token = cp_lexer_peek_token (parser->lexer); >- expression = cp_parser_expression (parser, /*cast_p=*/false, NULL); >- /* The standard requires that the expression have integral >- type. DR 74 adds enumeration types. We believe that the >- real intent is that these expressions be handled like the >- expression in a `switch' condition, which also allows >- classes with a single conversion to integral or >- enumeration type. */ >- if (!processing_template_decl) >+ expression >+ = build_expr_type_conversion (WANT_INT | WANT_ENUM, >+ expression, >+ /*complain=*/true); >+ if (!expression) > { >- expression >- = build_expr_type_conversion (WANT_INT | WANT_ENUM, >- expression, >- /*complain=*/true); >- if (!expression) >- { >- error_at (token->location, >- "expression in new-declarator must have integral " >- "or enumeration type"); >- expression = error_mark_node; >- } >+ error_at (token->location, >+ "expression in new-declarator must have integral " >+ "or enumeration type"); >+ expression = error_mark_node; > } > } >- /* But all the other expressions must be. */ >- else >- expression >- = cp_parser_constant_expression (parser, >- /*allow_non_constant=*/false, >- NULL); >+ > /* Look for the closing `]'. */ > cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); > >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C >index ea8f1eb..d3f14f4 100644 >--- a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C >@@ -7,8 +7,8 @@ int > main() { > > int a = 4; >- int b = 5; // { dg-message "not const" } >- int (*x)[b] = new int[a][b]; // { dg-error "not usable" } >+ int b = 5; >+ int (*x)[b] = new int[a][b]; // { dg-error "array size.*must be constant|usable in a constant" } > > x[2][1] = 7; > >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla5.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla5.C >index 021d484..2457e34 100644 >--- a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla5.C >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla5.C >@@ -6,5 +6,5 @@ > void > test (int a) > { >- new (char[a]); >+ new (char[a]); // { dg-warning "variable-length array" } > } >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla8.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla8.C >index 7b7428d..1c6000f 100644 >--- a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla8.C >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/ext/vla8.C >@@ -8,8 +8,8 @@ struct AvlTreeIter > > AvlTreeIter() > { >- new (void* [Num()]); >+ new (void* [Num()]); // { dg-warning "variable-length array" } > } > }; > >-AvlTreeIter<int> a; >+AvlTreeIter<int> a; // { dg-message "from here" } >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new35.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new35.C >new file mode 100644 >index 0000000..c5f79aa >--- /dev/null >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new35.C >@@ -0,0 +1,13 @@ >+// { dg-do compile } >+// { dg-options "" } >+ >+int >+main (int argc, char **argv) >+{ >+ typedef char A[argc]; >+ new A; // { dg-warning "variable-length array types|not a constant" } >+ new A[0]; // { dg-error "must be constant|not a constant" } >+ new A[5]; // { dg-error "must be constant|not a constant" } >+ new (A[0]); // { dg-error "must be constant|not a constant" } >+ new (A[5]); // { dg-error "must be constant|not a constant" } >+} >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new36.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new36.C >new file mode 100644 >index 0000000..c9b7af2 >--- /dev/null >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new36.C >@@ -0,0 +1,153 @@ >+// Testcase for invocation of constructors/destructors in operator new[]. >+// { dg-do run } >+ >+#include <stdlib.h> >+ >+struct E { >+ virtual ~E() { } >+}; >+ >+struct S { >+ S(); >+ ~S(); >+}; >+ >+static int count; >+static int max; >+static int throwAfter = -1; >+static S *pS; >+ >+S::S() >+{ >+ if (throwAfter >= 0 && count >= throwAfter) >+ throw E(); >+ if (pS) >+ { >+ ++pS; >+ if (this != pS) >+ abort(); >+ } >+ else >+ pS = this; >+ ++count; >+ max = count; >+} >+ >+S::~S() >+{ >+ if (count > 1) >+ { >+ if (this != pS) >+ abort(); >+ --pS; >+ } >+ else >+ pS = 0; >+ --count; >+} >+ >+void __attribute__((noinline)) doit(int n) >+{ >+ { >+ S *s = new S[n]; >+ if (count != n) >+ abort(); >+ if (pS != s + n - 1) >+ abort(); >+ delete [] s; >+ if (count != 0) >+ abort(); >+ } >+ throwAfter = 2; >+ max = 0; >+ try >+ { >+ new S[n]; >+ abort(); >+ } >+ catch (E) >+ { >+ if (max != 2) >+ abort(); >+ } >+ throwAfter = -1; >+} >+ >+int main() >+{ >+ { >+ S s; >+ if (count != 1) >+ abort(); >+ if (pS != &s) >+ abort(); >+ } >+ if (count != 0) >+ abort(); >+ { >+ S *s = new S; >+ if (count != 1) >+ abort(); >+ if (pS != s) >+ abort(); >+ delete s; >+ if (count != 0) >+ abort(); >+ } >+ { >+ S *s = new S[1]; >+ if (count != 1) >+ abort(); >+ if (pS != s) >+ abort(); >+ delete [] s; >+ if (count != 0) >+ abort(); >+ } >+ { >+ S *s = new S[5]; >+ if (count != 5) >+ abort(); >+ if (pS != s + 4) >+ abort(); >+ delete [] s; >+ if (count != 0) >+ abort(); >+ } >+ typedef S A[5]; >+ { >+ S *s = new A; >+ if (count != 5) >+ abort(); >+ if (pS != s + 4) >+ abort(); >+ delete [] s; >+ if (count != 0) >+ abort(); >+ } >+ throwAfter = 2; >+ max = 0; >+ try >+ { >+ new S[5]; >+ abort(); >+ } >+ catch (E) >+ { >+ if (max != 2) >+ abort(); >+ } >+ max = 0; >+ try >+ { >+ new A; >+ abort(); >+ } >+ catch (E) >+ { >+ if (max != 2) >+ abort(); >+ } >+ throwAfter = -1; >+ doit(5); >+} >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new37.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new37.C >new file mode 100644 >index 0000000..82ca18b >--- /dev/null >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new37.C >@@ -0,0 +1,63 @@ >+// { dg-do compile } >+ >+void >+nonconst(int n) >+{ >+ new (long[n][n]); // { dg-error "variable length|array size|not a constant" } >+ new long[n][n]; // { dg-error "variable length|array size|not a constant" } >+} >+ >+template <typename T> >+void * >+callnew(int n) >+{ >+ return new long[n][T::n]; >+} >+ >+template <typename T> >+void * >+callnew_fail_1(int n) >+{ >+ return new long[n][T::n]; // { dg-error "variable length|array size|usable in a constant" } >+} >+ >+template <typename T> >+void * >+callnew_fail_2() >+{ >+ return new long[T::n]; // { dg-error "size in array new" } >+} >+ >+template <typename T> >+void * >+callnew_fail_3() >+{ >+ return new T[2][T::n]; // { dg-error "size of array has non-integral type" } >+} >+ >+struct T1 { >+ static int n; >+}; >+ >+struct T2 { >+ static const double n = 2; // { dg-error "non-integral type" } >+}; >+ >+struct T3 { >+ static const int n = 2; >+}; >+ >+struct T4 { >+ enum { n = 3 }; >+}; >+ >+void >+test_callnew(int n) >+{ >+ new long[0.2]; // { dg-error "integral or enumeration type" } >+ callnew_fail_1<T1>(n); >+ callnew_fail_2<T2>(); >+ callnew_fail_3<T2>(); >+ callnew<T3>(n); >+ callnew<T4>(n); >+} >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new38.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new38.C >new file mode 100644 >index 0000000..1672f22 >--- /dev/null >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new38.C >@@ -0,0 +1,54 @@ >+// { dg-do compile } >+ >+void >+large_array_char(int n) >+{ >+ new char[n] >+ [1ULL << (sizeof(void *) * 4)] >+ [1ULL << (sizeof(void *) * 4)]; // { dg-error "size of array" } >+} >+ >+template <typename T> >+void >+large_array_char_template(int n) >+{ >+ new char[n] >+ [1ULL << (sizeof(void *) * 4)] >+ [1ULL << (sizeof(void *) * 4)]; // { dg-error "size of array" } >+} >+ >+ >+template <typename T> >+void >+large_array_template1(int n) >+{ >+ new T[n] // { dg-error "size of array is too large" } >+ [(1ULL << (sizeof(void *) * 4)) / sizeof(T)] >+ [1ULL << (sizeof(void *) * 4)]; >+} >+ >+template <typename T> >+void >+large_array_template2(int n) >+{ >+ new T[n] // { dg-error "size of array is too large" } >+ [(1ULL << (sizeof(void *) * 4)) / sizeof(T)] >+ [1ULL << (sizeof(void *) * 4)]; >+} >+ >+template <typename T> >+void >+large_array_template3(int n) >+{ >+ new T[n] // { dg-error "size of array is too large" } >+ [(1ULL << (sizeof(void *) * 4)) / sizeof(T)] >+ [1ULL << (sizeof(void *) * 4)]; >+} >+ >+void >+call_large_array_template(int n) >+{ >+ large_array_template1<char>(n); >+ large_array_template2<int>(n); >+ large_array_template3<double>(n); >+} >diff --git a/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new39.C b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new39.C >new file mode 100644 >index 0000000..f274ebb >--- /dev/null >+++ b/gcc-4.7.1-20120813/gcc/testsuite/g++.dg/init/new39.C >@@ -0,0 +1,68 @@ >+// Testcase for overflow handling in operator new[]. >+// { dg-do run } >+ >+#include <stdlib.h> >+#include <stdexcept> >+ >+struct without_new { >+ char bar[256]; >+}; >+ >+struct with_new { >+ char bar[256]; >+ void *operator new[] (size_t sz) >+ { >+ if (sz != -1) >+ abort (); >+ throw std::bad_alloc(); >+ } >+}; >+ >+template <typename T> >+inline void >+test (size_t s) >+{ >+ try { >+ new T[s]; >+ abort (); >+ } catch (std::bad_alloc &) { >+ } >+} >+ >+template <typename T> >+void >+test_noopt (size_t s) __attribute__((noinline)); >+ >+template <typename T> >+void >+test_noopt (size_t s) >+{ >+ __asm__ (""); >+ test<T> (s); >+} >+ >+template <typename T> >+void >+all_tests () >+{ >+ test<T>(-1); >+ test<T>(size_t(-1) / sizeof (T) + 1); >+ test<T>(size_t(-1) / sizeof (T) + 2); >+ test_noopt<T>(-1); >+ test_noopt<T>(size_t(-1) / sizeof (T) + 1); >+ test_noopt<T>(size_t(-1) / sizeof (T) + 2); >+} >+ >+int >+main () >+{ >+ try { >+ ::operator new(size_t(-1)); >+ abort (); >+ } catch (std::bad_alloc &) { >+ } >+ all_tests<without_new> (); >+ all_tests<with_new> (); >+ return 0; >+} >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 850911
:
606350
|
608498
|
608499
|
618101
|
618142
|
618143