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
This commit is contained in:
Marek Polacek 2015-03-27 09:33:20 +00:00 committed by Marek Polacek
parent 50cfd44e5d
commit 27674ca63c
4 changed files with 188 additions and 1 deletions

View 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

View 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.

View File

@ -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)
{
}
}

View 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,