ubsan.c (ubsan_source_location): Don't crash on unknown locations.
* 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
This commit is contained in:
parent
59b36ecf23
commit
0a508bb66b
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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" }
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue