re PR c++/90010 (valgrind error with snprintf and -Wall)
authorJakub Jelinek <jakub@redhat.com>
Wed, 10 Apr 2019 07:27:20 +0000 (09:27 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 10 Apr 2019 07:27:20 +0000 (09:27 +0200)
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.

From-SVN: r270246

gcc/ChangeLog
gcc/gimple-ssa-sprintf.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr90010.c [new file with mode: 0644]

index 9d21ce38b032473c643142368c0860e1f8487ba9..84d1205551c5513cda91846959d48a1b7c1d6d38 100644 (file)
@@ -1,3 +1,12 @@
+2019-04-10  Jakub Jelinek  <jakub@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.
+
 2019-04-09  Matthew Malcomson  <matthew.malcomson@arm.com>
 
        PR target/90024
index de60241379ad2cc0642d24b1a9649bb6a16fde0b..b6527bfc8d53a90d601db541becfa5bfe05c620e 100644 (file)
@@ -383,9 +383,14 @@ target_to_host (char *hostr, size_t hostsz, const char *targstr)
      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 hostsz, const char *targstr)
       if (!*targstr)
        break;
 
-      if (size_t (ph - hostr) == hostsz - 4)
+      if (size_t (ph - hostr) == hostsz)
        {
-         *ph = '\0';
-         strcat (ph, "...");
+         strcpy (ph - 4, "...");
          break;
        }
     }
index d8349c54cc071cf0b8b50ce02267aea8007ad155..2f6bda81385c7aedca0001d9b378ec5283a4c391 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-10  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/90010
+       * gcc.dg/pr90010.c: New test.
+
 2019-04-09  Uroš Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/i386/ifcvt-onecmpl-abs-1.c
diff --git a/gcc/testsuite/gcc.dg/pr90010.c b/gcc/testsuite/gcc.dg/pr90010.c
new file mode 100644 (file)
index 0000000..5cd5dd2
--- /dev/null
@@ -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);
+}