Skip to content

Commit

Permalink
c++: Don't crash upon invalid placement new operator [PR117101]
Browse files Browse the repository at this point in the history
We currently crash upon the following invalid code (notice the "void
void**" parameter)

=== cut here ===
using size_t = decltype(sizeof(int));
void *operator new(size_t, void void **p) noexcept { return p; }
int x;
void f() {
    int y;
    new (&y) int(x);
}
=== cut here ===

The problem is that in this case, we end up with a NULL_TREE parameter
list for the new operator because of the error, and (1) coerce_new_type
wrongly complains about the first parameter type not being size_t,
(2) std_placement_new_fn_p blindly accesses the parameter list, hence a
crash.

This patch does NOT address #1 since we can't easily distinguish between
a new operator declaration without parameters from one with erroneous
parameters (and it's not worth the risk to refactor and break things for
an error recovery issue) hence a dg-bogus in new52.C, but it does
address #2 and the ICE by simply checking the first parameter against
NULL_TREE.

It also adds a new testcase checking that we complain about new
operators with no or invalid first parameters, since we did not have
any.

	PR c++/117101

gcc/cp/ChangeLog:

	* init.cc (std_placement_new_fn_p): Check first_arg against
	NULL_TREE.

gcc/testsuite/ChangeLog:

	* g++.dg/init/new52.C: New test.
	* g++.dg/init/new53.C: New test.
  • Loading branch information
simartin committed Nov 5, 2024
1 parent b1d92ae commit 5821f5c
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 2 deletions.
5 changes: 3 additions & 2 deletions gcc/cp/init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2980,8 +2980,9 @@ std_placement_new_fn_p (tree alloc_fn)
if (DECL_NAMESPACE_SCOPE_P (alloc_fn))
{
tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
if ((TREE_VALUE (first_arg) == ptr_type_node)
&& TREE_CHAIN (first_arg) == void_list_node)
if (first_arg
&& (TREE_VALUE (first_arg) == ptr_type_node)
&& (TREE_CHAIN (first_arg) == void_list_node))
return true;
}
return false;
Expand Down
14 changes: 14 additions & 0 deletions gcc/testsuite/g++.dg/init/new52.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// PR c++/117101
// { dg-do "compile" { target c++11 } }

using size_t = decltype(sizeof(int));
void* operator new(size_t, // { dg-bogus "first parameter" "" { xfail *-*-* } }
void void **p) noexcept // { dg-error "two or more" }
{
return p; // { dg-error "not declared" }
}
int x;
void f() {
int y;
new (&y) int(x);
}
8 changes: 8 additions & 0 deletions gcc/testsuite/g++.dg/init/new53.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Check that we reject operator new with no argument or non-size_t first
// argument.
// { dg-do "compile" }

void* operator new(); // { dg-error "takes type .size_t." }
void* operator new(char); // { dg-error "takes type .size_t." }
void* operator new(char*); // { dg-error "takes type .size_t." }
void* operator new(char&); // { dg-error "takes type .size_t." }

0 comments on commit 5821f5c

Please sign in to comment.