public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Siddhesh Poyarekar <siddhesh@gotplt.org>
To: gcc-patches@gcc.gnu.org
Cc: jakub@redhat.com
Subject: Re: [PATCH] tree-object-size: Support strndup and strdup
Date: Thu, 15 Sep 2022 10:00:11 -0400	[thread overview]
Message-ID: <722b2d59-4482-a29f-b2e9-99d9242fda31@gotplt.org> (raw)
In-Reply-To: <3544076e-05f4-a69a-95bc-cc48190db699@gotplt.org>

Ping!

On 2022-09-07 15:21, Siddhesh Poyarekar wrote:
> Ping!
> 
> On 2022-08-29 10:16, Siddhesh Poyarekar wrote:
>> Ping!
>>
>> On 2022-08-15 15:23, Siddhesh Poyarekar wrote:
>>> 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 (get_whole_object): New function.
>>>     (addr_object_size): Use it.
>>>     (strdup_object_size): New function.
>>>     (call_object_size): Use it.
>>>     (pass_data_object_sizes, pass_data_early_object_sizes): Set
>>>     todo_flags_finish to TODO_update_ssa_no_phi.
>>>
>>> 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.
>>> ---
>>>   .../gcc.dg/builtin-dynamic-object-size-0.c    | 43 +++++++++++
>>>   .../gcc.dg/builtin-dynamic-object-size-1.c    |  2 +-
>>>   .../gcc.dg/builtin-dynamic-object-size-2.c    |  2 +-
>>>   .../gcc.dg/builtin-dynamic-object-size-3.c    |  2 +-
>>>   .../gcc.dg/builtin-dynamic-object-size-4.c    |  2 +-
>>>   gcc/testsuite/gcc.dg/builtin-object-size-1.c  | 64 +++++++++++++++-
>>>   gcc/testsuite/gcc.dg/builtin-object-size-2.c  | 63 ++++++++++++++-
>>>   gcc/testsuite/gcc.dg/builtin-object-size-3.c  | 63 ++++++++++++++-
>>>   gcc/testsuite/gcc.dg/builtin-object-size-4.c  | 63 ++++++++++++++-
>>>   gcc/tree-object-size.cc                       | 76 +++++++++++++++++--
>>>   10 files changed, 366 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c 
>>> b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
>>> index 01a280b2d7b..7f023708b15 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
>>> @@ -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) != 0)
>>> +    FAIL ();
>>>     if (nfails > 0)
>>>       __builtin_abort ();
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c 
>>> b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c
>>> index 7cc8b1c9488..8f17c8edcaf 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c
>>> @@ -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
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c 
>>> b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c
>>> index 267dbf48ca7..3677782ff1c 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c
>>> @@ -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
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c 
>>> b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c
>>> index fb9dc56da7e..5b6987b7773 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c
>>> @@ -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
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c 
>>> b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c
>>> index 870548b4206..9d796224e96 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c
>>> @@ -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
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c 
>>> b/gcc/testsuite/gcc.dg/builtin-object-size-1.c
>>> index b772e2da9b9..4fbd372d97a 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c
>>> @@ -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,64 @@ 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) != 64)
>>> +#endif
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +  free (ptr2);
>>> +}
>>> +
>>>   int
>>>   main (void)
>>>   {
>>> @@ -644,5 +705,6 @@ main (void)
>>>     test8 ();
>>>     test9 (1);
>>>     test10 ();
>>> +  test11 ();
>>>     exit (0);
>>>   }
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-2.c 
>>> b/gcc/testsuite/gcc.dg/builtin-object-size-2.c
>>> index 2729538da17..beb271c5afc 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-object-size-2.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-2.c
>>> @@ -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,63 @@ 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) != 64)
>>> +#endif
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +  free (ptr2);
>>> +}
>>> +
>>>   int
>>>   main (void)
>>>   {
>>> @@ -557,5 +617,6 @@ main (void)
>>>     test6 ();
>>>     test7 ();
>>>     test8 (1);
>>> +  test9 ();
>>>     exit (0);
>>>   }
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c 
>>> b/gcc/testsuite/gcc.dg/builtin-object-size-3.c
>>> index 44a99189776..5c878a14647 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c
>>> @@ -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,63 @@ 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) != 0)
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +
>>> +  res = strndup (ptr2, 32);
>>> +  if (__builtin_object_size (res, 2) != 0)
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +
>>> +  res = strndup (ptr2, 128);
>>> +  if (__builtin_object_size (res, 2) != 0)
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +
>>> +  res = strdup (ptr2);
>>> +#ifdef __builtin_object_size
>>> +  if (__builtin_object_size (res, 2) != 27)
>>> +#else
>>> +  if (__builtin_object_size (res, 2) != 0)
>>> +#endif
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +  free (ptr2);
>>> +}
>>> +
>>>   int
>>>   main (void)
>>>   {
>>> @@ -651,5 +711,6 @@ main (void)
>>>     test8 ();
>>>     test9 (1);
>>>     test10 ();
>>> +  test11 ();
>>>     exit (0);
>>>   }
>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c 
>>> b/gcc/testsuite/gcc.dg/builtin-object-size-4.c
>>> index b9fddfed036..0b1cb1e528a 100644
>>> --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c
>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c
>>> @@ -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,63 @@ 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) != 0)
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +
>>> +  res = strndup (ptr2, 32);
>>> +  if (__builtin_object_size (res, 3) != 0)
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +
>>> +  res = strndup (ptr2, 128);
>>> +  if (__builtin_object_size (res, 3) != 0)
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +
>>> +  res = strdup (ptr2);
>>> +#ifdef __builtin_object_size
>>> +  if (__builtin_object_size (res, 3) != 27)
>>> +#else
>>> +  if (__builtin_object_size (res, 3) != 0)
>>> +#endif
>>> +    abort ();
>>> +
>>> +  free (res);
>>> +  free (ptr2);
>>> +}
>>> +
>>>   int
>>>   main (void)
>>>   {
>>> @@ -530,5 +590,6 @@ main (void)
>>>     test6 ();
>>>     test7 ();
>>>     test8 (1);
>>> +  test9 ();
>>>     exit (0);
>>>   }
>>> diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
>>> index 4eb454a4a33..c075b71db56 100644
>>> --- a/gcc/tree-object-size.cc
>>> +++ b/gcc/tree-object-size.cc
>>> @@ -495,6 +495,18 @@ decl_init_size (tree decl, bool min)
>>>     return size;
>>>   }
>>> +/* Get the outermost object that PTR may point into.  */
>>> +
>>> +static tree
>>> +get_whole_object (const_tree ptr)
>>> +{
>>> +  tree pt_var = TREE_OPERAND (ptr, 0);
>>> +  while (handled_component_p (pt_var))
>>> +    pt_var = TREE_OPERAND (pt_var, 0);
>>> +
>>> +  return pt_var;
>>> +}
>>> +
>>>   /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
>>>      OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
>>>      If unknown, return size_unknown (object_size_type).  */
>>> @@ -514,9 +526,7 @@ addr_object_size (struct object_size_info *osi, 
>>> const_tree ptr,
>>>     if (pwholesize)
>>>       *pwholesize = size_unknown (object_size_type);
>>> -  pt_var = TREE_OPERAND (ptr, 0);
>>> -  while (handled_component_p (pt_var))
>>> -    pt_var = TREE_OPERAND (pt_var, 0);
>>> +  pt_var = get_whole_object (ptr);
>>>     if (!pt_var)
>>>       return false;
>>> @@ -789,6 +799,53 @@ 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 = is_strndup ? gimple_call_arg (call, 1) : NULL_TREE;
>>> +
>>> +  /* For strdup, simply emit strlen (SRC) + 1 and let the optimizer 
>>> fold it the
>>> +     way it likes.  */
>>> +  if (!is_strndup)
>>> +    {
>>> +      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));
>>> +    }
>>> +
>>> +  /* 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_whole_object (src);
>>> +
>>> +      if (!(object_size_type & OST_MINIMUM)
>>> +      || (wholesrc && TREE_CODE (wholesrc) == STRING_CST))
>>> +    compute_builtin_object_size (src, object_size_type, &sz);
>>> +    }
>>> +
>>> +  if (!n)
>>> +    return sz;
>>> +
>>> +  /* Factor in the N.  Note that with OST_MINIMUM, even if N is 
>>> known we return
>>> +     0 since the size could be less than N.  */
>>> +  return fold_build2 (MIN_EXPR, sizetype,
>>> +              fold_build2 (PLUS_EXPR, sizetype, size_one_node, n),
>>> +              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.
>>> @@ -1235,12 +1292,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);
>>> @@ -2113,7 +2177,7 @@ const pass_data pass_data_object_sizes =
>>>     PROP_objsz, /* properties_provided */
>>>     0, /* properties_destroyed */
>>>     0, /* todo_flags_start */
>>> -  0, /* todo_flags_finish */
>>> +  TODO_update_ssa_no_phi, /* todo_flags_finish */
>>>   };
>>>   class pass_object_sizes : public gimple_opt_pass
>>> @@ -2153,7 +2217,7 @@ const pass_data pass_data_early_object_sizes =
>>>     0, /* properties_provided */
>>>     0, /* properties_destroyed */
>>>     0, /* todo_flags_start */
>>> -  0, /* todo_flags_finish */
>>> +  TODO_update_ssa_no_phi, /* todo_flags_finish */
>>>   };
>>>   class pass_early_object_sizes : public gimple_opt_pass
>>
> 

  reply	other threads:[~2022-09-15 14:00 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-15 19:23 Siddhesh Poyarekar
2022-08-29 14:16 ` Siddhesh Poyarekar
2022-09-07 19:21   ` Siddhesh Poyarekar
2022-09-15 14:00     ` Siddhesh Poyarekar [this message]
2022-09-22 13:02 ` Jakub Jelinek
2022-09-22 15:26   ` Siddhesh Poyarekar
2022-09-23 13:02     ` Jakub Jelinek
2022-11-02 22:30       ` Siddhesh Poyarekar
2022-11-04 12:48 ` [PATCH v2] " Siddhesh Poyarekar
2022-11-04 13:43   ` Prathamesh Kulkarni
2022-11-04 13:47     ` Siddhesh Poyarekar
2022-11-17 19:47   ` Siddhesh Poyarekar
2022-11-20 15:42   ` Jeff Law
2022-11-21 14:27     ` Siddhesh Poyarekar
2022-11-22 20:43       ` Jeff Law
2022-11-22 23:13         ` Siddhesh Poyarekar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=722b2d59-4482-a29f-b2e9-99d9242fda31@gotplt.org \
    --to=siddhesh@gotplt.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).