aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2015-03-27 09:33:20 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2015-03-27 09:33:20 +0000
commit27674ca63c662a635f3a645a28790bde40ed11ab (patch)
tree73030549c624ef54877b624aed93c087329d3ac9 /gcc
parent50cfd44e5d1ed01d1c641da81ffe3974afa373f7 (diff)
downloadgcc-27674ca63c662a635f3a645a28790bde40ed11ab.zip
gcc-27674ca63c662a635f3a645a28790bde40ed11ab.tar.gz
gcc-27674ca63c662a635f3a645a28790bde40ed11ab.tar.bz2
re PR sanitizer/65583 ([UBSAN] ICE segfault in inline_edge_summary)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr65583.C140
-rw-r--r--gcc/ubsan.c35
4 files changed, 188 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e014dd8..37258ad 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 135dfc0..9cbe0f9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..4e1149e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr65583.C
@@ -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)
+ {
+ }
+}
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 0e23d91..b9d9f30 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -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,