public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
To: Siddhesh Poyarekar <siddhesh@gotplt.org>
Cc: gcc-patches@gcc.gnu.org, jakub@redhat.com
Subject: Re: [PATCH v2] tree-object-size: Support strndup and strdup
Date: Fri, 4 Nov 2022 19:13:19 +0530	[thread overview]
Message-ID: <CAAgBjMmcHQt8uhZSvWKE18_yVRYwE8sCM_Yg0Eb4a4v1XDRx0Q@mail.gmail.com> (raw)
In-Reply-To: <20221104124800.910588-1-siddhesh@gotplt.org>

On Fri, 4 Nov 2022 at 18:18, Siddhesh Poyarekar <siddhesh@gotplt.org> 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 (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.
> ---
> Tested:
>
> - x86_64 bootstrap and testsuite run
> - i686 build and testsuite run
> - ubsan bootstrap
>
>  .../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  | 94 +++++++++++++++++-
>  gcc/testsuite/gcc.dg/builtin-object-size-2.c  | 94 +++++++++++++++++-
>  gcc/testsuite/gcc.dg/builtin-object-size-3.c  | 95 ++++++++++++++++++-
>  gcc/testsuite/gcc.dg/builtin-object-size-4.c  | 94 +++++++++++++++++-
>  gcc/tree-object-size.cc                       | 84 +++++++++++++++-
>  10 files changed, 502 insertions(+), 10 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..4f1606a486b 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) != 1)
> +    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..c6e5b4c29f8 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,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);
>  }
> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-2.c
> index 2729538da17..639a83cfd39 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,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);
>  }
> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-3.c
> index 44a99189776..ff4f1747334 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,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);
>  }
> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-4.c
> index b9fddfed036..4c007c364b7 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,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);
>  }
> diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
> index 1f04cb80fd0..08e5731617d 100644
> --- a/gcc/tree-object-size.cc
> +++ b/gcc/tree-object-size.cc
> @@ -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,73 @@ 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.  */
> +  if (!is_strndup)
Sorry to nitpick, should this just be under else ? Since this
condition will be false if the above if (is_strndup)
is true.

Thanks,
Prathamesh
> +    {
> +      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 +1304,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 +2076,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 +2174,7 @@ object_sizes_execute (function *fun, bool early)
>      }
>
>    fini_object_sizes ();
> -  return 0;
> +  return todo;
>  }
>
>  /* Simple pass to optimize all __builtin_object_size () builtins.  */
> --
> 2.37.3
>

  reply	other threads:[~2022-11-04 13:43 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-15 19:23 [PATCH] " Siddhesh Poyarekar
2022-08-29 14:16 ` Siddhesh Poyarekar
2022-09-07 19:21   ` Siddhesh Poyarekar
2022-09-15 14:00     ` Siddhesh Poyarekar
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 [this message]
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=CAAgBjMmcHQt8uhZSvWKE18_yVRYwE8sCM_Yg0Eb4a4v1XDRx0Q@mail.gmail.com \
    --to=prathamesh.kulkarni@linaro.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=siddhesh@gotplt.org \
    /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).