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] errno can't alias locals (PR 92412)


The conditional in default_ref_may_alias_errno has the function
return true even for local variables, implying that locals must
be assumed not to have been changed across calls to errno-setting
functions like malloc.  This leads to both worse code and also
false negatives in the strlen pass' detection of buffer overflow
across such calls.

The attached patch constrains the conditional to only consider
external declarations.

Tested on x86_64-linux.

Martin
PR tree-optimization/92412 - excessive errno aliasing assumption defeats optimization

gcc/ChangeLog:

	PR tree-optimization/92412
	* targhooks.c (default_ref_may_alias_errno): Errono can only alias
	extern variables.

gcc/testsuite/ChangeLog:

	PR tree-optimization/92412
	* gcc.dg/strlenopt-91.c: New test.

Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(revision 278066)
+++ gcc/targhooks.c	(working copy)
@@ -1415,9 +1415,11 @@ default_ref_may_alias_errno (ao_ref *ref)
   if (TYPE_UNSIGNED (TREE_TYPE (base))
       || TYPE_MODE (TREE_TYPE (base)) != TYPE_MODE (integer_type_node))
     return false;
-  /* The default implementation assumes an errno location
-     declaration is never defined in the current compilation unit.  */
+  /* The default implementation assumes an errno location declaration
+     is never defined in the current compilation unit and may not be
+     aliased by a local variable.  */
   if (DECL_P (base)
+      && DECL_EXTERNAL (base)
       && !TREE_STATIC (base))
     return true;
   else if (TREE_CODE (base) == MEM_REF
Index: gcc/testsuite/gcc.dg/strlenopt-91.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-91.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-91.c	(working copy)
@@ -0,0 +1,124 @@
+/* PR tree-optimization/92412 - excessive errno aliasing assumption defeats
+   optimization
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fdump-tree-optimized" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void* alloca (size_t);
+extern void* calloc (size_t, size_t);
+extern void* malloc (size_t);
+
+extern const char exta[4];
+static char stata[] = "123";
+
+void sink (const void*, ...);
+
+#define T(ptr, alloc) do {						\
+    const char *p = ptr;						\
+    if (p[0] != '1' || p[1] != '2' || p[2] != '3' || p[3] != '\0'	\
+	|| __builtin_strlen (p) != 3)					\
+      return;								\
+									\
+    void *q = alloc;							\
+    __builtin_strcpy (q, p);						\
+									\
+    if (p[0] != '1' || p[1] != '2' || p[2] != '3' || p[3] != '\0'	\
+	|| __builtin_strlen (p) != 3					\
+	|| __builtin_strlen (q) != 3)					\
+      __builtin_abort ();						\
+									\
+    sink (p, q);							\
+  } while (0)
+
+
+void alloca_test_local (unsigned n)
+{
+  char loca[] = "123";
+  T (loca, alloca (n));
+}
+
+void alloca_test_extern_const (unsigned n)
+{
+  T (exta, alloca (n));
+}
+
+void alloca_test_static (unsigned n)
+{
+  T (stata, alloca (n));
+}
+
+
+// Verify fix for PR tree-optimization/92412.
+void calloc_test_local (unsigned m, unsigned n)
+{
+  char loca[] = "123";
+  T (loca, calloc (m, n));
+}
+
+void calloc_test_extern_const (unsigned m, unsigned n)
+{
+  T (exta, calloc (m, n));
+}
+
+void calloc_test_static (unsigned m, unsigned n)
+{
+  T (stata, calloc (m, n));
+}
+
+
+// Verify fix for PR tree-optimization/92412.
+void malloc_test_local (unsigned n)
+{
+  char loca[] = "123";
+  T (loca, malloc (n));
+}
+
+void malloc_test_extern_const (unsigned n)
+{
+  T (exta, malloc (n));
+}
+
+void malloc_test_static (unsigned n)
+{
+  T (stata, malloc (n));
+}
+
+
+#undef T
+#define T(ptr, n) do {							\
+    const char *p = ptr;						\
+    if (p[0] != '1' || p[1] != '2' || p[2] != '3' || p[3] != '\0'	\
+	|| __builtin_strlen (p) != 3)					\
+      return;								\
+									\
+    char vla[n];							\
+    char *q = vla;							\
+    __builtin_strcpy (q, p);						\
+									\
+    if (p[0] != '1' || p[1] != '2' || p[2] != '3' || p[3] != '\0'	\
+	|| __builtin_strlen (p) != 3					\
+	|| __builtin_strlen (q) != 3)					\
+      __builtin_abort ();						\
+									\
+    sink (p, vla);							\
+  } while (0)
+
+
+void vla_test_local (unsigned n)
+{
+  char loca[] = "123";
+  T (loca, n);
+}
+
+void vla_test_extern_const (unsigned n)
+{
+  T (exta, n);
+}
+
+void vla_test_static (unsigned n)
+{
+  T (stata, n);
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */

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