diff mbox series

c++: Fix another crash with invalid new operators [PR117463]

Message ID 0102019302eef2a1-a0296694-7644-43a4-9bef-83b862cf3566-000000@eu-west-1.amazonses.com
State New
Headers show
Series c++: Fix another crash with invalid new operators [PR117463] | expand

Commit Message

Simon Martin Nov. 6, 2024, 7:23 p.m. UTC
Even though this PR is very close to PR117101, it's not addressed by the
fix I made through r15-4958-g5821f5c8c89a05 because cxx_placement_new_fn
has the very same issue as std_placement_new_fn_p used to have.

This patch fixes the issue exactly the same, by checking the first
parameter against NULL_TREE. I considered somehow sharing code between
the two *_placement_new_fn* static functions, but it looked pointless
since the shared part ("the second parameter is the last one, and a
pointer") is unlikely to be useful elsewhere.

Successfully tested on x86_64-pc-linux-gnu.

	PR c++/117463

gcc/cp/ChangeLog:

	* constexpr.cc (cxx_placement_new_fn): Check first_arg against
	NULL_TREE.

gcc/testsuite/ChangeLog:

	* g++.dg/init/new54.C: New test.

---
 gcc/cp/constexpr.cc               |  3 ++-
 gcc/testsuite/g++.dg/init/new54.C | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/init/new54.C

Comments

Jason Merrill Nov. 6, 2024, 7:47 p.m. UTC | #1
On 11/6/24 2:23 PM, Simon Martin wrote:
> Even though this PR is very close to PR117101, it's not addressed by the
> fix I made through r15-4958-g5821f5c8c89a05 because cxx_placement_new_fn
> has the very same issue as std_placement_new_fn_p used to have.
> 
> This patch fixes the issue exactly the same, by checking the first
> parameter against NULL_TREE. I considered somehow sharing code between
> the two *_placement_new_fn* static functions, but it looked pointless
> since the shared part ("the second parameter is the last one, and a
> pointer") is unlikely to be useful elsewhere.

It seems those two functions are intended to test the exact same thing: 
whether the argument is ::operator new(size_t, void*).

I think cxx_placement_new_fn should just be

return (cxx_dialect >= cxx20 && std_placement_new_fn_p (fndecl));

and some of the tests in cxx_placement_new_fn move into 
std_placement_new_fn_p to accommodate callers that e.g. don't already 
know we're dealing with operator new.

> Successfully tested on x86_64-pc-linux-gnu.
> 
> 	PR c++/117463
> 
> gcc/cp/ChangeLog:
> 
> 	* constexpr.cc (cxx_placement_new_fn): Check first_arg against
> 	NULL_TREE.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/init/new54.C: New test.
> 
> ---
>   gcc/cp/constexpr.cc               |  3 ++-
>   gcc/testsuite/g++.dg/init/new54.C | 14 ++++++++++++++
>   2 files changed, 16 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/init/new54.C
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 71e6dc4ef32..379700ca2c1 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -2334,7 +2334,8 @@ cxx_placement_new_fn (tree fndecl)
>         && TREE_CODE (TREE_TYPE (fndecl)) == FUNCTION_TYPE)
>       {
>         tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
> -      if (TREE_VALUE (first_arg) == ptr_type_node
> +      if (first_arg
> +	  && TREE_VALUE (first_arg) == ptr_type_node
>   	  && TREE_CHAIN (first_arg) == void_list_node)
>   	return true;
>       }
> diff --git a/gcc/testsuite/g++.dg/init/new54.C b/gcc/testsuite/g++.dg/init/new54.C
> new file mode 100644
> index 00000000000..fdff1b55f0d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/init/new54.C
> @@ -0,0 +1,14 @@
> +// PR c++/117463
> +// { dg-do "compile" { target c++20 } }
> +
> +struct S {};
> +void *operator new[] (unsigned long, // { dg-bogus "first parameter" "" { xfail *-*-* } }
> +		      void void *volatile p); // { dg-error "two or more" }
> +S *fun(void *p) {
> +  return new(p) S[10];
> +}
> +
> +void *operator new (decltype(sizeof(0)), // { dg-bogus "first parameter" "" { xfail *-*-* } }
> +		    void void * p); // { dg-error "two or more" }
> +void *p;
> +auto t = new(p) int;
diff mbox series

Patch

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 71e6dc4ef32..379700ca2c1 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2334,7 +2334,8 @@  cxx_placement_new_fn (tree fndecl)
       && TREE_CODE (TREE_TYPE (fndecl)) == FUNCTION_TYPE)
     {
       tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
-      if (TREE_VALUE (first_arg) == ptr_type_node
+      if (first_arg
+	  && TREE_VALUE (first_arg) == ptr_type_node
 	  && TREE_CHAIN (first_arg) == void_list_node)
 	return true;
     }
diff --git a/gcc/testsuite/g++.dg/init/new54.C b/gcc/testsuite/g++.dg/init/new54.C
new file mode 100644
index 00000000000..fdff1b55f0d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new54.C
@@ -0,0 +1,14 @@ 
+// PR c++/117463
+// { dg-do "compile" { target c++20 } }
+
+struct S {};
+void *operator new[] (unsigned long, // { dg-bogus "first parameter" "" { xfail *-*-* } }
+		      void void *volatile p); // { dg-error "two or more" }
+S *fun(void *p) {
+  return new(p) S[10];
+}
+
+void *operator new (decltype(sizeof(0)), // { dg-bogus "first parameter" "" { xfail *-*-* } }
+		    void void * p); // { dg-error "two or more" }
+void *p;
+auto t = new(p) int;