tree-optimization/104970: Limit size computation for access attribute

Limit object size computation only to the simple case where access
attribute has been explicitly specified.  The object passed to
__builtin_dynamic_object_size could either be a pointer or a VLA whose
size has been described using access attribute.

Further, return a valid size only if the object is a void * pointer or
points to (or is a VLA of) a type that has a constant size.

gcc/ChangeLog:

	PR tree-optimization/104970
	* tree-object-size.cc (parm_object_size): Restrict size
	computation scenarios to explicit access attributes.

gcc/testsuite/ChangeLog:

	PR tree-optimization/104970
	* gcc.dg/builtin-dynamic-object-size-0.c (test_parmsz_simple2,
	test_parmsz_simple3, test_parmsz_extern, test_parmsz_internal,
	test_parmsz_internal2, test_parmsz_internal3): New tests.
	(main): Use them.

Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
This commit is contained in:
Siddhesh Poyarekar 2022-03-23 23:09:02 +05:30
parent 72124f487c
commit c1d233e333
2 changed files with 79 additions and 3 deletions

View File

@ -380,6 +380,22 @@ test_parmsz_simple (void *obj, size_t sz)
return __builtin_dynamic_object_size (obj, 0);
}
size_t
__attribute__ ((access (__read_write__, 2, 1)))
__attribute__ ((noinline))
test_parmsz_simple2 (size_t sz, char obj[])
{
return __builtin_dynamic_object_size (obj, 0);
}
/* Implicitly constructed access attributes not supported yet. */
size_t
__attribute__ ((noinline))
test_parmsz_simple3 (size_t sz, char obj[sz])
{
return __builtin_dynamic_object_size (obj, 0);
}
size_t
__attribute__ ((noinline))
__attribute__ ((access (__read_write__, 1, 2)))
@ -412,6 +428,38 @@ test_parmsz_unknown (void *obj, void *unknown, size_t sz, int cond)
return __builtin_dynamic_object_size (cond ? obj : unknown, 0);
}
struct S;
size_t
__attribute__ ((access (__read_write__, 1, 2)))
__attribute__ ((noinline))
test_parmsz_extern (struct S *obj, size_t sz)
{
return __builtin_dynamic_object_size (obj, 0);
}
/* Implicitly constructed access attributes not supported yet. */
size_t
__attribute__ ((noinline))
test_parmsz_internal (size_t sz, double obj[][sz])
{
return __builtin_dynamic_object_size (obj, 0);
}
size_t
__attribute__ ((access (__read_write__, 2, 1)))
__attribute__ ((noinline))
test_parmsz_internal2 (size_t sz, double obj[][sz])
{
return __builtin_dynamic_object_size (obj, 0);
}
size_t
__attribute__ ((noinline))
test_parmsz_internal3 (size_t sz1, size_t sz2, double obj[sz1][sz2])
{
return __builtin_dynamic_object_size (obj, 0);
}
/* Loops. */
size_t
@ -532,9 +580,22 @@ main (int argc, char **argv)
if (test_parmsz_simple (argv[0], __builtin_strlen (argv[0]) + 1)
!= __builtin_strlen (argv[0]) + 1)
FAIL ();
if (test_parmsz_simple2 (__builtin_strlen (argv[0]) + 1, argv[0])
!= __builtin_strlen (argv[0]) + 1)
FAIL ();
/* Only explicitly added access attributes are supported for now. */
if (test_parmsz_simple3 (__builtin_strlen (argv[0]) + 1, argv[0]) != -1)
FAIL ();
int arr[42];
if (test_parmsz_scaled (arr, 42) != sizeof (arr))
FAIL ();
if (test_parmsz_scaled (arr, 40) != 40 * sizeof (int))
FAIL ();
/* __bdos cannot see the actual size of ARR, so it will return what it was
passed. Fortunately though the overflow warnings see this caller side and
warns of the problematic size. */
if (test_parmsz_scaled (arr, 44) != 44 * sizeof (int)) /* { dg-warning "-Wstringop-overflow=" } */
FAIL ();
if (test_parmsz_unknown (argv[0], argv[0], __builtin_strlen (argv[0]) + 1, 0)
!= -1)
if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, -1) != 0)
@ -550,6 +611,16 @@ main (int argc, char **argv)
FAIL ();
if (test_parmsz_scaled_off (arr, 42, 2) != 40 * sizeof (int))
FAIL ();
struct S *s;
if (test_parmsz_extern (s, 42) != -1)
FAIL ();
double obj[4][4];
if (test_parmsz_internal (4, obj) != -1)
FAIL ();
if (test_parmsz_internal2 (4, obj) != -1)
FAIL ();
if (test_parmsz_internal3 (4, 4, obj) != -1)
FAIL ();
if (test_loop (arr, 42, 0, 32, 1) != 10 * sizeof (int))
FAIL ();
if (test_loop (arr, 42, 32, -1, -1) != 0)

View File

@ -1477,14 +1477,19 @@ parm_object_size (struct object_size_info *osi, tree var)
tree typesize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (parm)));
tree sz = NULL_TREE;
if (access && access->sizarg != UINT_MAX)
/* If we have an explicit access attribute with a usable size argument... */
if (access && access->sizarg != UINT_MAX && !access->internal_p
/* ... and either PARM is void * or has a type that is complete and has a
constant size... */
&& ((typesize && poly_int_tree_p (typesize))
|| (!typesize && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))))
{
tree fnargs = DECL_ARGUMENTS (fndecl);
tree arg = NULL_TREE;
unsigned argpos = 0;
/* Walk through the parameters to pick the size parameter and safely
scale it by the type size. */
/* ... then walk through the parameters to pick the size parameter and
safely scale it by the type size if needed. */
for (arg = fnargs; arg; arg = TREE_CHAIN (arg), ++argpos)
if (argpos == access->sizarg && INTEGRAL_TYPE_P (TREE_TYPE (arg)))
{