builtins.c (expand_builtin, [...]): Handle BUILT_IN_STRNCAT_CHK.
authorJakub Jelinek <jakub@redhat.com>
Mon, 23 Oct 2006 19:18:42 +0000 (21:18 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 23 Oct 2006 19:18:42 +0000 (21:18 +0200)
* builtins.c (expand_builtin, maybe_emit_chk_warning): Handle
BUILT_IN_STRNCAT_CHK.

* gcc.dg/builtin-strncat-chk-1.c: New test.

From-SVN: r117980

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtin-strncat-chk-1.c [new file with mode: 0644]

index c304f18a473a10883736ff1c325de161f1110050..5a6400a5fa4c962c238d56b49504a5ba60cd00f3 100644 (file)
@@ -1,3 +1,8 @@
+2006-10-23  Jakub Jelinek  <jakub@redhat.com>
+
+       * builtins.c (expand_builtin, maybe_emit_chk_warning): Handle
+       BUILT_IN_STRNCAT_CHK.
+
 2006-10-23  Jan Hubicka  <jh@suse.cz>
 
        * builtins.c (expand_builtin_memmove): Remove ORIG_EXP argument;
index b2a8647b9fa29c0dcdf22d978edb5bf8ab432ad7..5bd927b32e86505a38ad72e827b4d0fa741b9592 100644 (file)
@@ -6494,6 +6494,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_STPCPY_CHK:
     case BUILT_IN_STRNCPY_CHK:
     case BUILT_IN_STRCAT_CHK:
+    case BUILT_IN_STRNCAT_CHK:
     case BUILT_IN_SNPRINTF_CHK:
     case BUILT_IN_VSNPRINTF_CHK:
       maybe_emit_chk_warning (exp, fcode);
@@ -10243,6 +10244,11 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
       arg_mask = 6;
       is_strlen = 1;
       break;
+    case BUILT_IN_STRNCAT_CHK:
+    /* For __strncat_chk the warning will be emitted only if overflowing
+       by at least strlen (dest) + 1 bytes.  */
+      arg_mask = 12;
+      break;
     case BUILT_IN_STRNCPY_CHK:
       arg_mask = 12;
       break;
@@ -10280,6 +10286,22 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
       if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
        return;
     }
+  else if (fcode == BUILT_IN_STRNCAT_CHK)
+    {
+      tree src = TREE_VALUE (TREE_CHAIN (arglist));
+      if (! src || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
+       return;
+      src = c_strlen (src, 1);
+      if (! src || ! host_integerp (src, 1))
+       {
+         locus = EXPR_LOCATION (exp);
+         warning (0, "%Hcall to %D might overflow destination buffer",
+                  &locus, get_callee_fndecl (exp));
+         return;
+       }
+      else if (tree_int_cst_lt (src, size))
+       return;
+    }
   else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
     return;
 
index ebbae936261337fe4a40c2a71c326caf216e9f43..2a7f88bcae4910fcb401f10a156d6031729a6e58 100644 (file)
@@ -1,3 +1,7 @@
+2006-10-23  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.dg/builtin-strncat-chk-1.c: New test.
+
 2006-10-23  Jan Hubicka  <jh@suse.cz>
 
        * gcc.dg/memmove-1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/builtin-strncat-chk-1.c b/gcc/testsuite/gcc.dg/builtin-strncat-chk-1.c
new file mode 100644 (file)
index 0000000..80d7b9d
--- /dev/null
@@ -0,0 +1,38 @@
+/* Test whether buffer overflow warnings for __strncat_chk builtin
+   are emitted properly.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99" } */
+
+extern void abort (void);
+
+#include "../gcc.c-torture/execute/builtins/chk.h"
+
+char buf1[20];
+char *q;
+
+void
+test (int arg, ...)
+{
+  char *p = &buf1[10];
+
+  *p = 0;
+  strncat (p, "abcdefg", 9);
+  *p = 0;
+  strncat (p, "abcdefghi", 9);
+  *p = 0;
+  strncat (p, "abcdefghij", 9);
+  *p = 0;
+  strncat (p, "abcdefghi", 10);
+  *p = 0;
+  strncat (p, "abcdefghij", 10); /* { dg-warning "will always overflow" } */
+  *p = 0;
+  strncat (p, "abcdefgh", 11);
+  *p = 0;
+  strncat (p, "abcdefghijkl", 11); /* { dg-warning "will always overflow" } */
+  *p = 0;
+  strncat (p, q, 9);
+  *p = 0;
+  strncat (p, q, 10); /* { dg-warning "might overflow" } */
+  *p = 0;
+  strncat (p, q, 11); /* { dg-warning "might overflow" } */
+}