On April 9, 2019 11:47:28 PM GMT+02:00, Jakub Jelinek <ja...@redhat.com> wrote:
>Hi!
>
>As the following testcase shows, target_to_host handled
>targstr with strlen shorter than hostsz - 4 right (though with wasteful
>clearing of the rest of the buffer when only one '\0' termination is
>enough)
>and similarly also strlen hostsz and more right (making last 4
>characters
>in the buffer "..."), but anything in between resulted in random
>byte(s)
>at the end of the string (strncpy with hostsz - 4 length didn't zero
>terminate and because strlen (targstr) >= hostsz was false, nothing was
>appended).  When some target to host charset adjustment was needed, it
>appended that "..." even to strings that actually didn't need it.
>
>The following patch doesn't use "..." if targstr fits (including the
>zero
>termination), otherwise makes sure last 4 bytes in the buffer are
>"...".
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK. 

Richard. 

>2019-04-09  Jakub Jelinek  <ja...@redhat.com>
>
>       PR c++/90010
>       * gimple-ssa-sprintf.c (target_to_host): Fix handling of targstr
>       with strlen in between hostsz-3 and hostsz-1 inclusive when no
>       translation is needed, and when translation is needed, only append
>       ... if the string length is hostsz or more bytes long.  Avoid using
>       strncpy or strcat.
>
>       * gcc.dg/pr90010.c: New test.
>
>--- gcc/gimple-ssa-sprintf.c.jj        2019-04-09 12:25:41.000000000 +0200
>+++ gcc/gimple-ssa-sprintf.c   2019-04-09 14:01:04.875445413 +0200
>@@ -383,9 +383,14 @@ target_to_host (char *hostr, size_t host
>      overlong strings just like the translated strings are.  */
>   if (target_to_host_charmap['\0'] == 1)
>     {
>-      strncpy (hostr, targstr, hostsz - 4);
>-      if (strlen (targstr) >= hostsz)
>-      strcpy (hostr + hostsz - 4, "...");
>+      size_t len = strlen (targstr);
>+      if (len >= hostsz)
>+      {
>+        memcpy (hostr, targstr, hostsz - 4);
>+        strcpy (hostr + hostsz - 4, "...");
>+      }
>+      else
>+      memcpy (hostr, targstr, len + 1);
>       return hostr;
>     }
> 
>@@ -399,10 +404,9 @@ target_to_host (char *hostr, size_t host
>       if (!*targstr)
>       break;
> 
>-      if (size_t (ph - hostr) == hostsz - 4)
>+      if (size_t (ph - hostr) == hostsz)
>       {
>-        *ph = '\0';
>-        strcat (ph, "...");
>+        strcpy (ph - 4, "...");
>         break;
>       }
>     }
>--- gcc/testsuite/gcc.dg/pr90010.c.jj  2019-04-09 14:22:14.795791124
>+0200
>+++ gcc/testsuite/gcc.dg/pr90010.c     2019-04-09 14:26:10.274961523 +0200
>@@ -0,0 +1,27 @@
>+/* PR c++/90010 */
>+/* { dg-do compile } */
>+/* { dg-options "-Wall" } */
>+
>+char b[4096] = "abc";
>+void bar (char *);
>+
>+void
>+foo ()
>+{
>+  char d[4096];
>+  __builtin_snprintf (d, sizeof d, "%sfoobarbazquxquuxquuzthudfred",
>b);    /* { dg-warning "'foobarbazquxquuxquuzthudfred' directive output
>may be truncated writing 28 bytes into a region of size between 1 and
>4096" } */
>+  /* { dg-message "'__builtin_snprintf' output between 29 and 4124
>bytes into a destination of size 4096" "" { target *-*-* } .-1 } */
>+  bar (d);
>+  __builtin_snprintf (d, sizeof d, "%sfoobarbazquxquuxquuzcorgefred",
>b);    /* { dg-warning "'foobarbazquxquuxquuzcorgefred' directive output
>may be truncated writing 29 bytes into a region of size between 1 and
>4096" } */
>+  /* { dg-message "'__builtin_snprintf' output between 30 and 4125
>bytes into a destination of size 4096" "" { target *-*-* } .-1 } */
>+  bar (d);
>+  __builtin_snprintf (d, sizeof d, "%sfoobarbazquxquuxquuzcorgewaldo",
>b);    /* { dg-warning "'foobarbazquxquuxquuzcorgewaldo' directive output
>may be truncated writing 30 bytes into a region of size between 1 and
>4096" } */
>+  /* { dg-message "'__builtin_snprintf' output between 31 and 4126
>bytes into a destination of size 4096" "" { target *-*-* } .-1 } */
>+  bar (d);
>+  __builtin_snprintf (d, sizeof d,
>"%sfoobarbazquxquuxquuzcorgegarply", b);       /* { dg-warning
>"'foobarbazquxquuxquuzcorgegarply' directive output may be truncated
>writing 31 bytes into a region of size between 1 and 4096" } */
>+  /* { dg-message "'__builtin_snprintf' output between 32 and 4127
>bytes into a destination of size 4096" "" { target *-*-* } .-1 } */
>+  bar (d);
>+  __builtin_snprintf (d, sizeof d,
>"%sfoobarfredquxquuxquuzcorgegarply", b);      /* { dg-warning
>"'foobarfredquxquuxquuzcorgega\.\.\.' directive output may be truncated
>writing 32 bytes into a region of size between 1 and 4096" } */
>+  /* { dg-message "'__builtin_snprintf' output between 33 and 4128
>bytes into a destination of size 4096" "" { target *-*-* } .-1 } */
>+  bar (d);
>+}
>
>       Jakub

Reply via email to