mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 05:30:24 +08:00
tree-object-size: Support strndup and strdup
Use string length of input to strdup to determine the usable size of the resulting object. Avoid doing the same for strndup since there's a chance that the input may be too large, resulting in an unnecessary overhead or worse, the input may not be NULL terminated, resulting in a crash where there would otherwise have been none. gcc/ChangeLog: * tree-object-size.cc (todo): New variable. (object_sizes_execute): Use it. (strdup_object_size): New function. (call_object_size): Use it. gcc/testsuite/ChangeLog: * gcc.dg/builtin-dynamic-object-size-0.c (test_strdup, test_strndup, test_strdup_min, test_strndup_min): New tests. (main): Call them. * gcc.dg/builtin-dynamic-object-size-1.c: Silence overread warnings. * gcc.dg/builtin-dynamic-object-size-2.c: Likewise. * gcc.dg/builtin-dynamic-object-size-3.c: Likewise. * gcc.dg/builtin-dynamic-object-size-4.c: Likewise. * gcc.dg/builtin-object-size-1.c: Silence overread warnings. Declare free, strdup and strndup. (test11): New test. (main): Call it. * gcc.dg/builtin-object-size-2.c: Silence overread warnings. Declare free, strdup and strndup. (test9): New test. (main): Call it. * gcc.dg/builtin-object-size-3.c: Silence overread warnings. Declare free, strdup and strndup. (test11): New test. (main): Call it. * gcc.dg/builtin-object-size-4.c: Silence overread warnings. Declare free, strdup and strndup. (test9): New test. (main): Call it.
This commit is contained in:
parent
ec7c796de0
commit
e5cfb9cac1
@ -479,6 +479,40 @@ test_loop (int *obj, size_t sz, size_t start, size_t end, int incr)
|
||||
return __builtin_dynamic_object_size (ptr, 0);
|
||||
}
|
||||
|
||||
/* strdup/strndup. */
|
||||
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test_strdup (const char *in)
|
||||
{
|
||||
char *res = __builtin_strdup (in);
|
||||
return __builtin_dynamic_object_size (res, 0);
|
||||
}
|
||||
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test_strndup (const char *in, size_t bound)
|
||||
{
|
||||
char *res = __builtin_strndup (in, bound);
|
||||
return __builtin_dynamic_object_size (res, 0);
|
||||
}
|
||||
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test_strdup_min (const char *in)
|
||||
{
|
||||
char *res = __builtin_strdup (in);
|
||||
return __builtin_dynamic_object_size (res, 2);
|
||||
}
|
||||
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test_strndup_min (const char *in, size_t bound)
|
||||
{
|
||||
char *res = __builtin_strndup (in, bound);
|
||||
return __builtin_dynamic_object_size (res, 2);
|
||||
}
|
||||
|
||||
/* Other tests. */
|
||||
|
||||
struct TV4
|
||||
@ -651,6 +685,15 @@ main (int argc, char **argv)
|
||||
int *t = test_pr105736 (&val3);
|
||||
if (__builtin_dynamic_object_size (t, 0) != -1)
|
||||
FAIL ();
|
||||
const char *str = "hello world";
|
||||
if (test_strdup (str) != __builtin_strlen (str) + 1)
|
||||
FAIL ();
|
||||
if (test_strndup (str, 4) != 5)
|
||||
FAIL ();
|
||||
if (test_strdup_min (str) != __builtin_strlen (str) + 1)
|
||||
FAIL ();
|
||||
if (test_strndup_min (str, 4) != 1)
|
||||
FAIL ();
|
||||
|
||||
if (nfails > 0)
|
||||
__builtin_abort ();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
#define __builtin_object_size __builtin_dynamic_object_size
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
#define __builtin_object_size __builtin_dynamic_object_size
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
#define __builtin_object_size __builtin_dynamic_object_size
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
#define __builtin_object_size __builtin_dynamic_object_size
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
@ -7,10 +7,13 @@ extern void abort (void);
|
||||
extern void exit (int);
|
||||
extern void *malloc (size_t);
|
||||
extern void *calloc (size_t, size_t);
|
||||
extern void free (void *);
|
||||
extern void *alloca (size_t);
|
||||
extern void *memcpy (void *, const void *, size_t);
|
||||
extern void *memset (void *, int, size_t);
|
||||
extern char *strcpy (char *, const char *);
|
||||
extern char *strdup (const char *);
|
||||
extern char *strndup (const char *, size_t);
|
||||
|
||||
struct A
|
||||
{
|
||||
@ -629,6 +632,94 @@ test10 (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Tests for strdup/strndup. */
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test11 (void)
|
||||
{
|
||||
int i = 0;
|
||||
const char *ptr = "abcdefghijklmnopqrstuvwxyz";
|
||||
char *res = strndup (ptr, 21);
|
||||
if (__builtin_object_size (res, 0) != 22)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 32);
|
||||
if (__builtin_object_size (res, 0) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 0) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
char *ptr2 = malloc (64);
|
||||
strcpy (ptr2, ptr);
|
||||
|
||||
res = strndup (ptr2, 21);
|
||||
if (__builtin_object_size (res, 0) != 22)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 32);
|
||||
if (__builtin_object_size (res, 0) != 33)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 128);
|
||||
if (__builtin_object_size (res, 0) != 64)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr2);
|
||||
#ifdef __builtin_object_size
|
||||
if (__builtin_object_size (res, 0) != 27)
|
||||
#else
|
||||
if (__builtin_object_size (res, 0) != (size_t) -1)
|
||||
#endif
|
||||
abort ();
|
||||
free (res);
|
||||
free (ptr2);
|
||||
|
||||
ptr = "abcd\0efghijklmnopqrstuvwxyz";
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 0) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 24);
|
||||
if (__builtin_object_size (res, 0) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 2);
|
||||
if (__builtin_object_size (res, 0) != 3)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strdup (&ptr[4]);
|
||||
if (__builtin_object_size (res, 0) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 4);
|
||||
if (__builtin_object_size (res, 0) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 1);
|
||||
if (__builtin_object_size (res, 0) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -644,5 +735,6 @@ main (void)
|
||||
test8 ();
|
||||
test9 (1);
|
||||
test10 ();
|
||||
test11 ();
|
||||
exit (0);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
@ -7,10 +7,13 @@ extern void abort (void);
|
||||
extern void exit (int);
|
||||
extern void *malloc (size_t);
|
||||
extern void *calloc (size_t, size_t);
|
||||
extern void free (void *);
|
||||
extern void *alloca (size_t);
|
||||
extern void *memcpy (void *, const void *, size_t);
|
||||
extern void *memset (void *, int, size_t);
|
||||
extern char *strcpy (char *, const char *);
|
||||
extern char *strdup (const char *);
|
||||
extern char *strndup (const char *, size_t);
|
||||
|
||||
struct A
|
||||
{
|
||||
@ -544,6 +547,94 @@ test8 (unsigned cond)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Tests for strdup/strndup. */
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test9 (void)
|
||||
{
|
||||
const char *ptr = "abcdefghijklmnopqrstuvwxyz";
|
||||
char *res = strndup (ptr, 21);
|
||||
if (__builtin_object_size (res, 1) != 22)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 32);
|
||||
if (__builtin_object_size (res, 1) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 1) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
char *ptr2 = malloc (64);
|
||||
strcpy (ptr2, ptr);
|
||||
|
||||
res = strndup (ptr2, 21);
|
||||
if (__builtin_object_size (res, 1) != 22)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 32);
|
||||
if (__builtin_object_size (res, 1) != 33)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 128);
|
||||
if (__builtin_object_size (res, 1) != 64)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr2);
|
||||
#ifdef __builtin_object_size
|
||||
if (__builtin_object_size (res, 1) != 27)
|
||||
#else
|
||||
if (__builtin_object_size (res, 1) != (size_t) -1)
|
||||
#endif
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
free (ptr2);
|
||||
|
||||
ptr = "abcd\0efghijklmnopqrstuvwxyz";
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 1) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 24);
|
||||
if (__builtin_object_size (res, 1) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 2);
|
||||
if (__builtin_object_size (res, 1) != 3)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strdup (&ptr[4]);
|
||||
if (__builtin_object_size (res, 1) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 4);
|
||||
if (__builtin_object_size (res, 1) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 1);
|
||||
if (__builtin_object_size (res, 1) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -557,5 +648,6 @@ main (void)
|
||||
test6 ();
|
||||
test7 ();
|
||||
test8 (1);
|
||||
test9 ();
|
||||
exit (0);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
@ -7,10 +7,13 @@ extern void abort (void);
|
||||
extern void exit (int);
|
||||
extern void *malloc (size_t);
|
||||
extern void *calloc (size_t, size_t);
|
||||
extern void free (void *);
|
||||
extern void *alloca (size_t);
|
||||
extern void *memcpy (void *, const void *, size_t);
|
||||
extern void *memset (void *, int, size_t);
|
||||
extern char *strcpy (char *, const char *);
|
||||
extern char *strdup (const char *);
|
||||
extern char *strndup (const char *, size_t);
|
||||
|
||||
struct A
|
||||
{
|
||||
@ -636,6 +639,95 @@ test10 (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Tests for strdup/strndup. */
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test11 (void)
|
||||
{
|
||||
const char *ptr = "abcdefghijklmnopqrstuvwxyz";
|
||||
char *res = strndup (ptr, 21);
|
||||
if (__builtin_object_size (res, 2) != 22)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 32);
|
||||
if (__builtin_object_size (res, 2) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 2) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
char *ptr2 = malloc (64);
|
||||
strcpy (ptr2, ptr);
|
||||
|
||||
res = strndup (ptr2, 21);
|
||||
if (__builtin_object_size (res, 2) != 1)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 32);
|
||||
if (__builtin_object_size (res, 2) != 1)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 128);
|
||||
if (__builtin_object_size (res, 2) != 1)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr2);
|
||||
|
||||
#ifdef __builtin_object_size
|
||||
if (__builtin_object_size (res, 2) != 27)
|
||||
#else
|
||||
if (__builtin_object_size (res, 2) != 1)
|
||||
#endif
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
free (ptr2);
|
||||
|
||||
ptr = "abcd\0efghijklmnopqrstuvwxyz";
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 2) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 24);
|
||||
if (__builtin_object_size (res, 2) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 2);
|
||||
if (__builtin_object_size (res, 2) != 3)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strdup (&ptr[4]);
|
||||
if (__builtin_object_size (res, 2) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 4);
|
||||
if (__builtin_object_size (res, 2) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 1);
|
||||
if (__builtin_object_size (res, 2) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -651,5 +743,6 @@ main (void)
|
||||
test8 ();
|
||||
test9 (1);
|
||||
test10 ();
|
||||
test11 ();
|
||||
exit (0);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
/* { dg-options "-O2 -Wno-stringop-overread" } */
|
||||
/* { dg-require-effective-target alloca } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
@ -7,10 +7,13 @@ extern void abort (void);
|
||||
extern void exit (int);
|
||||
extern void *malloc (size_t);
|
||||
extern void *calloc (size_t, size_t);
|
||||
extern void free (void *);
|
||||
extern void *alloca (size_t);
|
||||
extern void *memcpy (void *, const void *, size_t);
|
||||
extern void *memset (void *, int, size_t);
|
||||
extern char *strcpy (char *, const char *);
|
||||
extern char *strdup (const char *);
|
||||
extern char *strndup (const char *, size_t);
|
||||
|
||||
struct A
|
||||
{
|
||||
@ -517,6 +520,94 @@ test8 (unsigned cond)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Tests for strdup/strndup. */
|
||||
size_t
|
||||
__attribute__ ((noinline))
|
||||
test9 (void)
|
||||
{
|
||||
const char *ptr = "abcdefghijklmnopqrstuvwxyz";
|
||||
char *res = strndup (ptr, 21);
|
||||
if (__builtin_object_size (res, 3) != 22)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 32);
|
||||
if (__builtin_object_size (res, 3) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 3) != 27)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
char *ptr2 = malloc (64);
|
||||
strcpy (ptr2, ptr);
|
||||
|
||||
res = strndup (ptr2, 21);
|
||||
if (__builtin_object_size (res, 3) != 1)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 32);
|
||||
if (__builtin_object_size (res, 3) != 1)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr2, 128);
|
||||
if (__builtin_object_size (res, 3) != 1)
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
|
||||
res = strdup (ptr2);
|
||||
#ifdef __builtin_object_size
|
||||
if (__builtin_object_size (res, 3) != 27)
|
||||
#else
|
||||
if (__builtin_object_size (res, 3) != 1)
|
||||
#endif
|
||||
abort ();
|
||||
|
||||
free (res);
|
||||
free (ptr2);
|
||||
|
||||
ptr = "abcd\0efghijklmnopqrstuvwxyz";
|
||||
res = strdup (ptr);
|
||||
if (__builtin_object_size (res, 3) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 24);
|
||||
if (__builtin_object_size (res, 3) != 5)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (ptr, 2);
|
||||
if (__builtin_object_size (res, 3) != 3)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strdup (&ptr[4]);
|
||||
if (__builtin_object_size (res, 3) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 4);
|
||||
if (__builtin_object_size (res, 3) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
|
||||
res = strndup (&ptr[4], 1);
|
||||
if (__builtin_object_size (res, 3) != 1)
|
||||
abort ();
|
||||
free (res);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -530,5 +621,6 @@ main (void)
|
||||
test6 ();
|
||||
test7 ();
|
||||
test8 (1);
|
||||
test9 ();
|
||||
exit (0);
|
||||
}
|
||||
|
@ -89,6 +89,10 @@ static bitmap computed[OST_END];
|
||||
/* Maximum value of offset we consider to be addition. */
|
||||
static unsigned HOST_WIDE_INT offset_limit;
|
||||
|
||||
/* Tell the generic SSA updater what kind of update is needed after the pass
|
||||
executes. */
|
||||
static unsigned todo;
|
||||
|
||||
/* Return true if VAL represents an initial size for OBJECT_SIZE_TYPE. */
|
||||
|
||||
static inline bool
|
||||
@ -787,6 +791,71 @@ alloc_object_size (const gcall *call, int object_size_type)
|
||||
return bytes ? bytes : size_unknown (object_size_type);
|
||||
}
|
||||
|
||||
/* Compute __builtin_object_size for CALL, which is a call to either
|
||||
BUILT_IN_STRDUP or BUILT_IN_STRNDUP; IS_STRNDUP indicates which it is.
|
||||
OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
|
||||
If unknown, return size_unknown (object_size_type). */
|
||||
|
||||
static tree
|
||||
strdup_object_size (const gcall *call, int object_size_type, bool is_strndup)
|
||||
{
|
||||
tree src = gimple_call_arg (call, 0);
|
||||
tree sz = size_unknown (object_size_type);
|
||||
tree n = NULL_TREE;
|
||||
|
||||
if (is_strndup)
|
||||
n = fold_build2 (PLUS_EXPR, sizetype, size_one_node,
|
||||
gimple_call_arg (call, 1));
|
||||
/* For strdup, simply emit strlen (SRC) + 1 and let the optimizer fold it the
|
||||
way it likes. */
|
||||
else
|
||||
{
|
||||
tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
|
||||
if (strlen_fn)
|
||||
{
|
||||
sz = fold_build2 (PLUS_EXPR, sizetype, size_one_node,
|
||||
build_call_expr (strlen_fn, 1, src));
|
||||
todo = TODO_update_ssa_only_virtuals;
|
||||
}
|
||||
}
|
||||
|
||||
/* In all other cases, return the size of SRC since the object size cannot
|
||||
exceed that. We cannot do this for OST_MINIMUM unless SRC points into a
|
||||
string constant since otherwise the object size could go all the way down
|
||||
to zero. */
|
||||
if (!size_valid_p (sz, object_size_type)
|
||||
|| size_unknown_p (sz, object_size_type))
|
||||
{
|
||||
tree wholesrc = NULL_TREE;
|
||||
if (TREE_CODE (src) == ADDR_EXPR)
|
||||
wholesrc = get_base_address (TREE_OPERAND (src, 0));
|
||||
|
||||
/* If the source points within a string constant, we try to get its
|
||||
length. */
|
||||
if (wholesrc && TREE_CODE (wholesrc) == STRING_CST)
|
||||
{
|
||||
tree len = c_strlen (src, 0);
|
||||
if (len)
|
||||
sz = fold_build2 (PLUS_EXPR, sizetype, size_one_node, len);
|
||||
}
|
||||
|
||||
/* For maximum estimate, our next best guess is the object size of the
|
||||
source. */
|
||||
if (size_unknown_p (sz, object_size_type)
|
||||
&& !(object_size_type & OST_MINIMUM))
|
||||
compute_builtin_object_size (src, object_size_type, &sz);
|
||||
}
|
||||
|
||||
/* String duplication allocates at least one byte, so we should never fail
|
||||
for OST_MINIMUM. */
|
||||
if ((!size_valid_p (sz, object_size_type)
|
||||
|| size_unknown_p (sz, object_size_type))
|
||||
&& (object_size_type & OST_MINIMUM))
|
||||
sz = size_one_node;
|
||||
|
||||
/* Factor in the N. */
|
||||
return n ? fold_build2 (MIN_EXPR, sizetype, n, sz) : sz;
|
||||
}
|
||||
|
||||
/* If object size is propagated from one of function's arguments directly
|
||||
to its return value, return that argument for GIMPLE_CALL statement CALL.
|
||||
@ -1233,12 +1302,19 @@ call_object_size (struct object_size_info *osi, tree ptr, gcall *call)
|
||||
{
|
||||
int object_size_type = osi->object_size_type;
|
||||
unsigned int varno = SSA_NAME_VERSION (ptr);
|
||||
tree bytes = NULL_TREE;
|
||||
|
||||
gcc_assert (is_gimple_call (call));
|
||||
|
||||
gcc_assert (!object_sizes_unknown_p (object_size_type, varno));
|
||||
gcc_assert (osi->pass == 0);
|
||||
tree bytes = alloc_object_size (call, object_size_type);
|
||||
|
||||
bool is_strdup = gimple_call_builtin_p (call, BUILT_IN_STRDUP);
|
||||
bool is_strndup = gimple_call_builtin_p (call, BUILT_IN_STRNDUP);
|
||||
if (is_strdup || is_strndup)
|
||||
bytes = strdup_object_size (call, object_size_type, is_strndup);
|
||||
else
|
||||
bytes = alloc_object_size (call, object_size_type);
|
||||
|
||||
if (!size_valid_p (bytes, object_size_type))
|
||||
bytes = size_unknown (object_size_type);
|
||||
@ -1998,6 +2074,8 @@ dynamic_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call)
|
||||
static unsigned int
|
||||
object_sizes_execute (function *fun, bool early)
|
||||
{
|
||||
todo = 0;
|
||||
|
||||
basic_block bb;
|
||||
FOR_EACH_BB_FN (bb, fun)
|
||||
{
|
||||
@ -2094,7 +2172,7 @@ object_sizes_execute (function *fun, bool early)
|
||||
}
|
||||
|
||||
fini_object_sizes ();
|
||||
return 0;
|
||||
return todo;
|
||||
}
|
||||
|
||||
/* Simple pass to optimize all __builtin_object_size () builtins. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user