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:
parent
50cfd44e5d
commit
27674ca63c
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
35
gcc/ubsan.c
35
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,
|
||||
|
|
Loading…
Reference in New Issue