This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix __builtin_*_chk (PR middle-end/23484)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 19 Aug 2005 16:35:32 -0400
- Subject: [PATCH] Fix __builtin_*_chk (PR middle-end/23484)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
I have made a thinko in maxlen handling in a bunch of __builtin_*_chk
folders. If len (e.g. for memcpy_chk this is the 3rd argument given
by the user) is not a compile time constant and the compiler manages
to compute maxlen as the maximum possible length of the source buffer,
then I set len = maxlen. The intention was that the next
if (tree_int_cst_lt (size, len))
return 0;
comparison really wants to work either with len (provided it is compile
time constant), or with maxlen (if len is not constant, but maxlen is).
Unfortunately, in the routines len is used afterwards as the argument
passed to memcpy etc. calls the builtins transform into, if size
of destination buffer is not shorter than maxlen, so in the testcase
from PR GCC mistakenly replaced the notint ? sizeof (tmp) : 4 argument
with 8 (maxlen).
Fixed thusly, the change in fold_builtin_stxcpy_chk is just to keep
all routines similar, len is never used there.
Ok to commit?
2005-08-19 Jakub Jelinek <jakub@redhat.com>
PR middle-end/23484
* builtins.c (fold_builtin_memory_chk, fold_builtin_stxcpy_chk,
fold_builtin_strncpy_chk, fold_builtin_snprintf_chk): If len is
not constant, but maxlen is, don't set len to maxlen, rather
set maxlen to len if len is a constant.
* gcc.c-torture/execute/builtins/pr23484-chk.c: New test.
* gcc.c-torture/execute/builtins/pr23484-chk-lib.c: New file.
--- gcc/builtins.c.jj 2005-08-16 16:23:55.000000000 +0200
+++ gcc/builtins.c 2005-08-19 22:24:21.000000000 +0200
@@ -10119,10 +10119,11 @@ fold_builtin_memory_chk (tree fndecl, tr
}
return 0;
}
- len = maxlen;
}
+ else
+ maxlen = len;
- if (tree_int_cst_lt (size, len))
+ if (tree_int_cst_lt (size, maxlen))
return 0;
}
@@ -10224,10 +10225,11 @@ fold_builtin_stxcpy_chk (tree fndecl, tr
return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
build_function_call_expr (fn, arglist));
}
- len = maxlen;
}
-
- if (! tree_int_cst_lt (len, size))
+ else
+ maxlen = len;
+
+ if (! tree_int_cst_lt (maxlen, size))
return 0;
}
@@ -10272,10 +10274,11 @@ fold_builtin_strncpy_chk (tree arglist,
if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
return 0;
- len = maxlen;
}
+ else
+ maxlen = len;
- if (tree_int_cst_lt (size, len))
+ if (tree_int_cst_lt (size, maxlen))
return 0;
}
@@ -10541,10 +10544,11 @@ fold_builtin_snprintf_chk (tree arglist,
if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
return 0;
- len = maxlen;
}
+ else
+ maxlen = len;
- if (tree_int_cst_lt (size, len))
+ if (tree_int_cst_lt (size, maxlen))
return 0;
}
--- gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.c.jj 2005-08-19 21:23:26.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.c 2005-08-19 22:22:25.000000000 +0200
@@ -0,0 +1,61 @@
+/* PR middle-end/23484 */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen (const char *);
+extern void *memcpy (void *, const void *, size_t);
+extern void *mempcpy (void *, const void *, size_t);
+extern void *memmove (void *, const void *, size_t);
+extern int snprintf (char *, size_t, const char *, ...);
+extern int memcmp (const void *, const void *, size_t);
+
+#include "chk.h"
+
+static char data[8] = "ABCDEFG";
+
+int l1;
+
+void
+__attribute__((noinline))
+test1 (void)
+{
+ char buf[8];
+
+ /* All the checking calls in this routine have a maximum length, so
+ object size checking should be done at compile time if optimizing. */
+ chk_calls = 0;
+
+ memset (buf, 'I', sizeof (buf));
+ if (memcpy (buf, data, l1 ? sizeof (buf) : 4) != buf
+ || memcmp (buf, "ABCDIIII", 8))
+ abort ();
+
+ memset (buf, 'J', sizeof (buf));
+ if (mempcpy (buf, data, l1 ? sizeof (buf) : 4) != buf + 4
+ || memcmp (buf, "ABCDJJJJ", 8))
+ abort ();
+
+ memset (buf, 'K', sizeof (buf));
+ if (memmove (buf, data, l1 ? sizeof (buf) : 4) != buf
+ || memcmp (buf, "ABCDKKKK", 8))
+ abort ();
+
+ memset (buf, 'L', sizeof (buf));
+ if (snprintf (buf, l1 ? sizeof (buf) : 4, "%d", l1 + 65536) != 5
+ || memcmp (buf, "655\0LLLL", 8))
+ abort ();
+
+ if (chk_calls)
+ abort ();
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE__
+ /* Object size checking is only intended for -O[s123]. */
+ return;
+#endif
+ __asm ("" : "=r" (l1) : "0" (l1));
+ test1 ();
+}
--- gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk-lib.c.jj 2005-08-19 21:23:22.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk-lib.c 2005-06-27 14:17:38.000000000 +0200
@@ -0,0 +1 @@
+#include "lib/chk.c"
Jakub