PR c++/67942 - diagnose placement new buffer overflow

gcc/cp/
	* cp/init.c (warn_placement_new_too_small): Avoid assuming
	the size of the first operand of placement new or its type
	is known.

gcc/testsuite/
	* g++.dg/warn/Wplacement-new-size.C: Exercise placement new
	invocations where the size of the destination buffer object
	or its type (or both) is unknown.

From-SVN: r229831
This commit is contained in:
Martin Sebor 2015-11-06 01:08:53 +00:00 committed by Martin Sebor
parent 925b6a76e2
commit 906f9ad995
4 changed files with 68 additions and 3 deletions

View File

@ -1,3 +1,10 @@
2015-11-05 Martin Sebor <msebor@redhat.com>
PR c++/67942
* cp/init.c (warn_placement_new_too_small): Avoid assuming
the size of the first operand of placement new or its type
is known.
2015-11-05 Martin Sebor <msebor@redhat.com>
PR c++/67942

View File

@ -2384,20 +2384,26 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
/* Treat members of unions and members of structs uniformly, even
though the size of a member of a union may be viewed as extending
to the end of the union itself (it is by __builtin_object_size). */
if (TREE_CODE (oper) == VAR_DECL || use_obj_size)
if ((TREE_CODE (oper) == VAR_DECL || use_obj_size)
&& DECL_SIZE_UNIT (oper))
{
/* Use the size of the entire array object when the expression
refers to a variable or its size depends on an expression
that's not a compile-time constant. */
bytes_avail = tree_to_shwi (DECL_SIZE_UNIT (oper));
bytes_avail = tree_to_uhwi (DECL_SIZE_UNIT (oper));
exact_size = !use_obj_size;
}
else
else if (TYPE_SIZE_UNIT (TREE_TYPE (oper)))
{
/* Use the size of the type of the destination buffer object
as the optimistic estimate of the available space in it. */
bytes_avail = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (oper)));
}
else
{
/* Bail if neither the size of the object nor its type is known. */
return;
}
/* Avoid diagnosing flexible array members (accepted as an extension
and diagnosed with -Wpedantic).

View File

@ -1,3 +1,10 @@
2015-11-05 Martin Sebor <msebor@redhat.com>
PR c++/67942
* g++.dg/warn/Wplacement-new-size.C: Exercise placement new
invocations where the size of the destination buffer object
or its type (or both) is unknown.
2015-11-05 Martin Sebor <msebor@redhat.com>
PR c++/67942

View File

@ -408,3 +408,48 @@ void test_user_defined_placement_new ()
new (&x) ClassWithGlobalNew[2];
}
}
extern char extbuf[];
template <class> struct TemplateClass { char c; };
// Declare a specialization but don't provide a definition.
template <> struct TemplateClass<void>;
// Declare an object of an explicit specialization of an unknown size.
extern TemplateClass<void> exttempl_void;
// Verify that no warning is issued when placement new is called with
// an extern buffer of unknown size (and the case is handled gracefully
// and doesn't cause an ICE).
static __attribute__ ((used))
void test_extern_buffer_of_unknown_size ()
{
new (extbuf) int ();
new (extbuf) int [1024];
new (&exttempl_void) int ();
new (&exttempl_void) int [1024];
}
extern char extbuf_size_int [sizeof (int)];
extern TemplateClass<int> exttempl;
// Verify that a warning is issued as expected when placement new is
// called with an extern buffer of known size (and the case is handled
// gracefully and doesn't cause an ICE).
static __attribute__ ((used))
void test_extern_buffer ()
{
new (extbuf_size_int) int ();
new (extbuf_size_int) int [1];
struct S { int a [2]; };
new (extbuf_size_int) S; // { dg-warning "placement" }
new (extbuf_size_int) int [2]; // { dg-warning "placement" }
new (&exttempl) int (); // { dg-warning "placement" }
new (&exttempl) int [1024]; // { dg-warning "placement" }
}