]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ubsan.c (ubsan_source_location): Don't crash on unknown locations.
authorJakub Jelinek <jakub@redhat.com>
Fri, 22 Nov 2013 20:07:31 +0000 (21:07 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 22 Nov 2013 20:07:31 +0000 (21:07 +0100)
* ubsan.c (ubsan_source_location): Don't crash on
unknown locations.
(ubsan_pass): Ignore clobber stmts.

* sanitizer.def (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN): New built-in.
* opts.c (common_handle_option): Add -fsanitize=return.
* flag-types.h (enum sanitize_code): Add SANITIZE_RETURN and
or it into SANITIZE_UNDEFINED.
c-family/
* c-ubsan.h (ubsan_instrument_return): New prototype.
* c-ubsan.c (ubsan_instrument_return): New function.
cp/
* cp-gimplify.c: Include target.h and c-family/c-ubsan.h.
(cp_ubsan_maybe_instrument_return): New function.
(cp_genericize): Call it if -fsanitize=return.
testsuite/
* g++.dg/ubsan/return-1.C: New test.
* g++.dg/ubsan/return-2.C: New test.

From-SVN: r205283

13 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-ubsan.c
gcc/c-family/c-ubsan.h
gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/flag-types.h
gcc/opts.c
gcc/sanitizer.def
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ubsan/return-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/return-2.C [new file with mode: 0644]
gcc/ubsan.c

index 334d082d9dca2721299ae3944e61113deb87f51f..f380e4459b1cc07e183d7b7115a0f8b793396663 100644 (file)
@@ -1,5 +1,14 @@
 2013-11-22  Jakub Jelinek  <jakub@redhat.com>
 
+       * ubsan.c (ubsan_source_location): Don't crash on
+       unknown locations.
+       (ubsan_pass): Ignore clobber stmts.
+
+       * sanitizer.def (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN): New built-in.
+       * opts.c (common_handle_option): Add -fsanitize=return.
+       * flag-types.h (enum sanitize_code): Add SANITIZE_RETURN and
+       or it into SANITIZE_UNDEFINED.
+
        * sanitizer.def (BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT,
        BUILT_IN_ASAN_AFTER_DYNAMIC_INIT): New.
        * asan.c (instrument_derefs): Handle also VAR_DECL loads/stores.
index 358ab47f785c48c1bd933a61ef67e66feb8e77f2..43c4dad09458ba62134772b71ea5744d711aed7c 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-ubsan.h (ubsan_instrument_return): New prototype.
+       * c-ubsan.c (ubsan_instrument_return): New function.
+
 2013-11-22  Andrew MacLeod  <amacleod@redhat.com>
 
        * c-common.c: Add required include files from gimple.h.
index 7a09e7b9596005aa9f834985fbd0d6d978b0cf74..a2769352be47f54369c2679f4a034a1c52ff0eba 100644 (file)
@@ -179,3 +179,14 @@ ubsan_instrument_vla (location_t loc, tree size)
 
   return t;
 }
+
+/* Instrument missing return in C++ functions returning non-void.  */
+
+tree
+ubsan_instrument_return (location_t loc)
+{
+  tree data = ubsan_create_data ("__ubsan_missing_return_data", loc,
+                                NULL, NULL_TREE);
+  tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN);
+  return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
+}
index fdf27d9e21e9e5abf7feeec34333c2712d711394..9b91bad8cdc19b9a0ca7e1dcb9a9648208146ca7 100644 (file)
@@ -24,5 +24,6 @@ along with GCC; see the file COPYING3.  If not see
 extern tree ubsan_instrument_division (location_t, tree, tree);
 extern tree ubsan_instrument_shift (location_t, enum tree_code, tree, tree);
 extern tree ubsan_instrument_vla (location_t, tree);
+extern tree ubsan_instrument_return (location_t);
 
 #endif  /* GCC_C_UBSAN_H  */
index 479d919b73be3e8e1e75fe8d8b00fe6022fb7ce0..ee0674c230006de76804889688f2aa667e3147b0 100644 (file)
@@ -1,5 +1,9 @@
 2013-11-22  Jakub Jelinek  <jakub@redhat.com>
 
+       * cp-gimplify.c: Include target.h and c-family/c-ubsan.h.
+       (cp_ubsan_maybe_instrument_return): New function.
+       (cp_genericize): Call it if -fsanitize=return.
+
        * decl2.c: Include asan.h.
        (one_static_initialization_or_destruction): If -fsanitize=address,
        init is non-NULL and guard is NULL, set
index 176dbc36aaab7c849af403774b48bd72a94f9bd8..b1270a187f1dc6eb074411a6c72c87bfeee5bac4 100644 (file)
@@ -39,6 +39,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "hashtab.h"
 #include "flags.h"
 #include "splay-tree.h"
+#include "target.h"
+#include "c-family/c-ubsan.h"
 
 /* Forward declarations.  */
 
@@ -1178,6 +1180,59 @@ cp_genericize_tree (tree* t_p)
   wtd.bind_expr_stack.release ();
 }
 
+/* If a function that should end with a return in non-void
+   function doesn't obviously end with return, add ubsan
+   instrmentation code to verify it at runtime.  */
+
+static void
+cp_ubsan_maybe_instrument_return (tree fndecl)
+{
+  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
+      || DECL_CONSTRUCTOR_P (fndecl)
+      || DECL_DESTRUCTOR_P (fndecl)
+      || !targetm.warn_func_return (fndecl))
+    return;
+
+  tree t = DECL_SAVED_TREE (fndecl);
+  while (t)
+    {
+      switch (TREE_CODE (t))
+       {
+       case BIND_EXPR:
+         t = BIND_EXPR_BODY (t);
+         continue;
+       case TRY_FINALLY_EXPR:
+         t = TREE_OPERAND (t, 0);
+         continue;
+       case STATEMENT_LIST:
+         {
+           tree_stmt_iterator i = tsi_last (t);
+           if (!tsi_end_p (i))
+             {
+               t = tsi_stmt (i);
+               continue;
+             }
+         }
+         break;
+       case RETURN_EXPR:
+         return;
+       default:
+         break;
+       }
+      break;
+    }
+  if (t == NULL_TREE)
+    return;
+  t = DECL_SAVED_TREE (fndecl);
+  if (TREE_CODE (t) == BIND_EXPR
+      && TREE_CODE (BIND_EXPR_BODY (t)) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator i = tsi_last (BIND_EXPR_BODY (t));
+      t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl));
+      tsi_link_after (&i, t, TSI_NEW_STMT);
+    }
+}
+
 void
 cp_genericize (tree fndecl)
 {
@@ -1240,6 +1295,9 @@ cp_genericize (tree fndecl)
      walk_tree's hash functionality.  */
   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
 
+  if (flag_sanitize & SANITIZE_RETURN)
+    cp_ubsan_maybe_instrument_return (fndecl);
+
   /* Do everything else.  */
   c_genericize (fndecl);
 
index 528c88a370c0b43e1a29798f5853bbc0d1b163f4..1d85a9aa4e85b451a2f4116f926b8fecf91172d7 100644 (file)
@@ -212,8 +212,9 @@ enum sanitize_code {
   SANITIZE_UNREACHABLE = 1 << 4,
   SANITIZE_VLA = 1 << 5,
   SANITIZE_NULL = 1 << 6,
+  SANITIZE_RETURN = 1 << 7,
   SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
-                      | SANITIZE_VLA | SANITIZE_NULL
+                      | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
 };
 
 /* flag_vtable_verify initialization levels. */
index 5a9d7c81a726669b4a72d325dbe874513d777bae..21ca9dcdf7aefd75aa5805d047769e8587499267 100644 (file)
@@ -1457,6 +1457,7 @@ common_handle_option (struct gcc_options *opts,
              { "unreachable", SANITIZE_UNREACHABLE,
                sizeof "unreachable" - 1 },
              { "vla-bound", SANITIZE_VLA, sizeof "vla-bound" - 1 },
+             { "return", SANITIZE_RETURN, sizeof "return" - 1 },
              { "null", SANITIZE_NULL, sizeof "null" - 1 },
              { NULL, 0, 0 }
            };
index ad1248dd999fe17ebcbb6befd2974562210f14e0..5bf1e3cebe6215d64e52ea299b436b645cd44442 100644 (file)
@@ -303,6 +303,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE,
                      "__ubsan_handle_builtin_unreachable",
                      BT_FN_VOID_PTR,
                      ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MISSING_RETURN,
+                     "__ubsan_handle_missing_return",
+                     BT_FN_VOID_PTR,
+                     ATTR_NORETURN_NOTHROW_LEAF_LIST)
 DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE,
                      "__ubsan_handle_vla_bound_not_positive",
                      BT_FN_VOID_PTR_PTR,
index a98a7b97a135f44291847b785b59ff44d9d527ff..091cc52c84d3dc79d5e16a536feb8aa988a36355 100644 (file)
@@ -1,5 +1,8 @@
 2013-11-22  Jakub Jelinek  <jakub@redhat.com>
 
+       * g++.dg/ubsan/return-1.C: New test.
+       * g++.dg/ubsan/return-2.C: New test.
+
        * c-c++-common/asan/no-redundant-instrumentation-1.c: Tweak to avoid
        optimizing away some __asan_report* calls.
 
diff --git a/gcc/testsuite/g++.dg/ubsan/return-1.C b/gcc/testsuite/g++.dg/ubsan/return-1.C
new file mode 100644 (file)
index 0000000..43791b9
--- /dev/null
@@ -0,0 +1,27 @@
+// { dg-do run }
+// { dg-options "-fsanitize=return" }
+// { dg-shouldfail "ubsan" }
+
+struct S { S (); ~S (); };
+
+S::S () {}
+S::~S () {}
+
+int
+foo (int x)
+{
+  S a;
+  {
+    S b;
+    if (x)
+      return 1;
+  }
+}
+
+int
+main ()
+{
+  foo (0);
+}
+
+// { dg-output "execution reached the end of a value-returning function without returning a value" }
diff --git a/gcc/testsuite/g++.dg/ubsan/return-2.C b/gcc/testsuite/g++.dg/ubsan/return-2.C
new file mode 100644 (file)
index 0000000..c7380f0
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do run }
+// { dg-options "-fsanitize=return" }
+
+struct S { S (); ~S (); };
+
+S::S () {}
+S::~S () {}
+
+int
+foo (int x)
+{
+  S a;
+  {
+    S b;
+    if (x)
+      return 1;
+  }
+}
+
+int
+main ()
+{
+  foo (1);
+  foo (14);
+}
index 5effd55acfb15832635f17abd4c53cd027065e6b..f2b66bf4d571867513095e6d5b9f783d100f370f 100644 (file)
@@ -229,8 +229,8 @@ ubsan_source_location (location_t loc)
   xloc = expand_location (loc);
 
   /* Fill in the values from LOC.  */
-  size_t len = strlen (xloc.file);
-  tree str = build_string (len + 1, xloc.file);
+  size_t len = xloc.file ? strlen (xloc.file) : 0;
+  tree str = build_string (len + 1, xloc.file ? xloc.file : "");
   TREE_TYPE (str) = build_array_type (char_type_node,
                                      build_index_type (size_int (len)));
   TREE_READONLY (str) = 1;
@@ -644,7 +644,7 @@ ubsan_pass (void)
        {
          struct walk_stmt_info wi;
          gimple stmt = gsi_stmt (gsi);
-         if (is_gimple_debug (stmt))
+         if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
            {
              gsi_next (&gsi);
              continue;