re PR sanitizer/65583 ([UBSAN] ICE segfault in inline_edge_summary)
authorMarek Polacek <polacek@redhat.com>
Fri, 27 Mar 2015 09:33:20 +0000 (09:33 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Fri, 27 Mar 2015 09:33:20 +0000 (09:33 +0000)
PR sanitizer/65583
* ubsan.c (ubsan_create_edge): New function.
(instrument_bool_enum_load): Call it.
(instrument_nonnull_arg): Likewise.
(instrument_nonnull_return): Likewise.
(instrument_object_size): Likewise.

* g++.dg/ubsan/pr65583.C: New test.

From-SVN: r221723

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ubsan/pr65583.C [new file with mode: 0644]
gcc/ubsan.c

index e014dd89e32bad9db945808514afdc466fe485a0..37258ad187cb39e84ec732e03424e331b247c4d5 100644 (file)
@@ -1,3 +1,12 @@
+2015-03-27  Marek Polacek  <polacek@redhat.com>
+
+       PR sanitizer/65583
+       * ubsan.c (ubsan_create_edge): New function.
+       (instrument_bool_enum_load): Call it.
+       (instrument_nonnull_arg): Likewise.
+       (instrument_nonnull_return): Likewise.
+       (instrument_object_size): Likewise.
+
 2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
 
        * lto-streamer.h (class lto_location_cache): Turn loc_cache into
index 135dfc03e9e05062b9adf256a836ccd6f17abf68..9cbe0f93570887efe1e88f5c529278e01ab22cd6 100644 (file)
@@ -1,3 +1,8 @@
+2015-03-27  Marek Polacek  <polacek@redhat.com>
+
+       PR sanitizer/65583
+       * g++.dg/ubsan/pr65583.C: New test.
+
 2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
 
        * gcc.c-torture/compile/20150327.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/ubsan/pr65583.C b/gcc/testsuite/g++.dg/ubsan/pr65583.C
new file mode 100644 (file)
index 0000000..4e1149e
--- /dev/null
@@ -0,0 +1,140 @@
+// PR sanitizer/65583
+// { dg-do compile }
+// { dg-options "-std=c++11 -fsanitize=undefined" }
+
+namespace std
+{
+  inline namespace __cxx11
+  {
+  }
+  template < typename > class allocator;
+    template < class _CharT > struct char_traits;
+  namespace __cxx11
+  {
+    template < typename _CharT, typename _Traits =
+      char_traits < _CharT >, typename _Alloc =
+      allocator < _CharT > >class basic_string;
+    typedef basic_string < char >string;
+  }
+}
+namespace std
+{
+  template < typename _Tp, _Tp __v > struct integral_constant
+  {
+    static constexpr _Tp value = __v;
+  };
+  typedef integral_constant < bool, true > true_type;
+}
+namespace __gnu_cxx
+{
+  template < typename _Tp > class new_allocator
+  {
+  public:
+    typedef long unsigned size_type;
+    typedef _Tp value_type;
+      template < typename _Tp1 > struct rebind
+    {
+      typedef new_allocator < _Tp1 > other;
+    };
+  };
+}
+namespace std
+{
+  template < typename _Tp > using __allocator_base =
+    __gnu_cxx::new_allocator < _Tp >;
+  template < typename _Tp > class allocator:public __allocator_base < _Tp >
+  {
+  };
+  template < typename _Alloc, typename _Tp > class __alloctr_rebind_helper
+  {
+    template < typename _Alloc2, typename _Tp2 >
+      static constexpr true_type _S_chk (typename _Alloc2::template rebind <
+                                        _Tp2 >::other *);
+  public:
+    using __type = decltype (_S_chk < _Alloc, _Tp > (nullptr));
+  };
+  template < typename _Alloc, typename _Tp, bool =
+    __alloctr_rebind_helper < _Alloc,
+    _Tp >::__type::value > struct __alloctr_rebind;
+  template < typename _Alloc, typename _Tp > struct __alloctr_rebind <_Alloc,
+    _Tp, true >
+  {
+    typedef typename _Alloc::template rebind < _Tp >::other __type;
+  };
+  template < typename _Alloc > struct allocator_traits
+  {
+    typedef typename _Alloc::value_type value_type;
+    static value_type *_S_pointer_helper (...);
+    typedef decltype (_S_pointer_helper ((_Alloc *) 0)) __pointer;
+    typedef __pointer pointer;
+      template < typename _Tp >
+      static typename _Tp::size_type _S_size_type_helper (_Tp *);
+    typedef decltype (_S_size_type_helper ((_Alloc *) 0)) __size_type;
+    typedef __size_type size_type;
+      template < typename _Tp > using rebind_alloc =
+      typename __alloctr_rebind < _Alloc, _Tp >::__type;
+  };
+}
+namespace __gnu_cxx
+{
+  template < typename _Alloc > struct __alloc_traits:std::allocator_traits <
+    _Alloc >
+  {
+    typedef std::allocator_traits < _Alloc > _Base_type;
+      template < typename _Tp > struct rebind
+    {
+      typedef typename _Base_type::template rebind_alloc < _Tp > other;
+    };
+  };
+}
+namespace std
+{
+  namespace __cxx11
+  {
+    template < typename _CharT, typename _Traits,
+      typename _Alloc > class basic_string
+    {
+      typedef typename __gnu_cxx::__alloc_traits < _Alloc >::template rebind <
+       _CharT >::other _Char_alloc_type;
+      typedef __gnu_cxx::__alloc_traits < _Char_alloc_type > _Alloc_traits;
+      typedef _Char_alloc_type allocator_type;
+      typedef typename _Alloc_traits::size_type size_type;
+      typedef typename _Alloc_traits::pointer pointer;
+      struct _Alloc_hider:allocator_type
+      {
+       _Alloc_hider (pointer __dat, const _Alloc & __a)
+       {
+       }
+      };
+      _Alloc_hider _M_dataplus;
+      union
+      {
+       size_type _M_allocated_capacity;
+      };
+      pointer _M_local_data ()
+      {
+      }
+      void _M_dispose ()
+      {
+       _M_destroy (_M_allocated_capacity);
+      }
+      void _M_destroy (size_type __size) throw ()
+      {
+      }
+    public:
+    basic_string (const _CharT * __s, const _Alloc & __a = _Alloc ()):_M_dataplus (_M_local_data (),
+                  __a)
+      {
+       _M_dispose ();
+      }
+    };
+  }
+  class FileHandle
+  {
+    std::string fname;
+    FileHandle (const char *fname);
+  };
+  FileHandle::FileHandle (const char *fname):fname (fname)
+  {
+  }
+}
index 0e23d919744de85acd93193db5ae3ad79013c73f..b9d9f30e66028f735fcf949072f5b691039c3581 100644 (file)
@@ -686,6 +686,21 @@ is_ubsan_builtin_p (tree t)
                     "__builtin___ubsan_", 18) == 0;
 }
 
+/* Create a callgraph edge for statement STMT.  */
+
+static void
+ubsan_create_edge (gimple stmt)
+{
+  gcall *call_stmt = dyn_cast <gcall *> (stmt);
+  basic_block bb = gimple_bb (stmt);
+  int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
+  cgraph_node *node = cgraph_node::get (current_function_decl);
+  tree decl = gimple_call_fndecl (call_stmt);
+  if (decl)
+    node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count,
+                      freq);
+}
+
 /* Expand the UBSAN_BOUNDS special builtin function.  */
 
 bool
@@ -1483,6 +1498,7 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
     }
   gimple_set_location (g, loc);
   gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
+  ubsan_create_edge (g);
   *gsi = gsi_for_stmt (stmt);
 }
 
@@ -1670,6 +1686,7 @@ instrument_nonnull_arg (gimple_stmt_iterator *gsi)
            }
          gimple_set_location (g, loc[0]);
          gsi_insert_before (gsi, g, GSI_SAME_STMT);
+         ubsan_create_edge (g);
        }
       *gsi = gsi_for_stmt (stmt);
     }
@@ -1722,6 +1739,7 @@ instrument_nonnull_return (gimple_stmt_iterator *gsi)
        }
       gimple_set_location (g, loc[0]);
       gsi_insert_before (gsi, g, GSI_SAME_STMT);
+      ubsan_create_edge (g);
       *gsi = gsi_for_stmt (stmt);
     }
   flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
@@ -1818,6 +1836,7 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
 
   tree sizet;
   tree base_addr = base;
+  gimple bos_stmt = NULL;
   if (decl_p)
     base_addr = build1 (ADDR_EXPR,
                        build_pointer_type (TREE_TYPE (base)), base);
@@ -1834,6 +1853,17 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
                                   integer_zero_node);
       sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
                                        GSI_SAME_STMT);
+      /* If the call above didn't end up being an integer constant, go one
+        statement back and get the __builtin_object_size stmt.  Save it,
+        we might need it later.  */
+      if (SSA_VAR_P (sizet))
+       {
+         gsi_prev (gsi);
+         bos_stmt = gsi_stmt (*gsi);
+
+         /* Move on to where we were.  */
+         gsi_next (gsi);
+       }
     }
   else
     return;
@@ -1870,7 +1900,10 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
        }
     }
 
-  /* Nope.  Emit the check.  */
+  if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
+    ubsan_create_edge (bos_stmt);
+
+  /* We have to emit the check.  */
   t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
                                GSI_SAME_STMT);
   ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,