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