This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix __builtin_*_chk (PR middle-end/23484)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]