sanitizer: do not inline no-sanitize into sanitizer fn
authorMartin Liska <mliska@suse.cz>
Tue, 9 Jun 2020 11:03:55 +0000 (13:03 +0200)
committerMartin Liska <mliska@suse.cz>
Tue, 9 Jun 2020 12:35:43 +0000 (14:35 +0200)
gcc/ChangeLog:

* cif-code.def (ATTRIBUTE_MISMATCH): Rename to...
(SANITIZE_ATTRIBUTE_MISMATCH): ...this.
* ipa-inline.c (sanitize_attrs_match_for_inline_p):
Handle all sanitizer options.
(can_inline_edge_p): Use renamed CIF_* enum value.

gcc/testsuite/ChangeLog:

* c-c++-common/asan/inline.c: New test.
* c-c++-common/asan/inline-kernel.c: New test.
* c-c++-common/tsan/inline.c: New test.
* c-c++-common/ubsan/inline.c: New test.

gcc/cif-code.def
gcc/ipa-inline.c
gcc/testsuite/c-c++-common/asan/inline-kernel.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/asan/inline.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tsan/inline.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/inline.c [new file with mode: 0644]

index 31c18c6c69149b22ad66c8c98e6fedfc0447c75a..c65b2477203a48b1145820d1ac8216ff389ef492 100644 (file)
@@ -128,9 +128,10 @@ DEFCIFCODE(OPTIMIZATION_MISMATCH, CIF_FINAL_ERROR,
 DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_ERROR,
           N_("callee refers to comdat-local symbols"))
 
-/* We can't inline because of mismatched caller/callee attributes.  */
-DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
-          N_("function attribute mismatch"))
+/* We can't inline because of mismatched caller/callee
+   sanitizer attributes.  */
+DEFCIFCODE(SANITIZE_ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
+          N_("sanitizer function attribute mismatch"))
 
 /* We can't inline because the user requests only static functions
    but the function has external linkage for live patching purpose.  */
index f71443feff7ede97477d19bb79d7b6c98a4734c4..c667de2a97cfb748ffce6cf6e778d6da25717b03 100644 (file)
@@ -264,18 +264,26 @@ sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee)
   if (!caller || !callee)
     return true;
 
-  /* Allow inlining always_inline functions into no_sanitize_address
-     functions.  */
-  if (!sanitize_flags_p (SANITIZE_ADDRESS, caller)
-      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee)))
+  /* Follow clang and allow inlining for always_inline functions.  */
+  if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee)))
     return true;
 
-  return ((sanitize_flags_p (SANITIZE_ADDRESS, caller)
-          == sanitize_flags_p (SANITIZE_ADDRESS, callee))
-         && (sanitize_flags_p (SANITIZE_POINTER_COMPARE, caller)
-             == sanitize_flags_p (SANITIZE_POINTER_COMPARE, callee))
-         && (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT, caller)
-             == sanitize_flags_p (SANITIZE_POINTER_SUBTRACT, callee)));
+  const sanitize_code codes[] =
+    {
+      SANITIZE_ADDRESS,
+      SANITIZE_THREAD,
+      SANITIZE_UNDEFINED,
+      SANITIZE_UNDEFINED_NONDEFAULT,
+      SANITIZE_POINTER_COMPARE,
+      SANITIZE_POINTER_SUBTRACT
+    };
+
+  for (unsigned i = 0; i < sizeof (codes) / sizeof (codes[0]); i++)
+    if (sanitize_flags_p (codes[i], caller)
+       != sanitize_flags_p (codes[i], callee))
+      return false;
+
+  return true;
 }
 
 /* Used for flags where it is safe to inline when caller's value is
@@ -382,7 +390,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
   /* Don't inline a function with mismatched sanitization attributes. */
   else if (!sanitize_attrs_match_for_inline_p (caller->decl, callee->decl))
     {
-      e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
+      e->inline_failed = CIF_SANITIZE_ATTRIBUTE_MISMATCH;
       inlinable = false;
     }
   if (!inlinable && report)
diff --git a/gcc/testsuite/c-c++-common/asan/inline-kernel.c b/gcc/testsuite/c-c++-common/asan/inline-kernel.c
new file mode 100644 (file)
index 0000000..4ca739b
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=kernel-address -c -O3 -fdump-tree-optimized" } */
+
+int x;
+
+static inline
+__attribute__((no_sanitize("kernel-address")))
+void do_not_sanitize(void)
+{
+  x++;
+}
+
+void
+sanitize_this(void)
+{
+  x++;
+  do_not_sanitize();
+}
+
+/* { dg-final { scan-tree-dump-times "Function do_not_sanitize" 1 "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/inline.c b/gcc/testsuite/c-c++-common/asan/inline.c
new file mode 100644 (file)
index 0000000..7c36702
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=address -c -O3 -fdump-tree-optimized" } */
+
+int x;
+
+static inline
+__attribute__((no_sanitize("address")))
+void do_not_sanitize(void)
+{
+  x++;
+}
+
+void
+sanitize_this(void)
+{
+  x++;
+  do_not_sanitize();
+}
+
+/* { dg-final { scan-tree-dump-times "Function do_not_sanitize" 1 "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/tsan/inline.c b/gcc/testsuite/c-c++-common/tsan/inline.c
new file mode 100644 (file)
index 0000000..7fb3e57
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=thread -c -O3 -fdump-tree-optimized" } */
+
+int x;
+
+static inline
+__attribute__((no_sanitize("thread")))
+void do_not_sanitize(void)
+{
+  x++;
+}
+
+void
+sanitize_this(void)
+{
+  x++;
+  do_not_sanitize();
+}
+
+/* { dg-final { scan-tree-dump-times "Function do_not_sanitize" 1 "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/inline.c b/gcc/testsuite/c-c++-common/ubsan/inline.c
new file mode 100644 (file)
index 0000000..de96604
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=vla-bound -c -O3 -fdump-tree-optimized" } */
+
+int x;
+
+static inline
+__attribute__((no_sanitize("undefined")))
+void do_not_sanitize(void)
+{
+  x++;
+}
+
+void
+sanitize_this(void)
+{
+  x++;
+  do_not_sanitize();
+}
+
+/* { dg-final { scan-tree-dump-times "Function do_not_sanitize" 1 "optimized" } } */