aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog33
-rw-r--r--gcc/asan.c8
-rw-r--r--gcc/asan.h27
-rw-r--r--gcc/builtins.def3
-rw-r--r--gcc/c-family/ChangeLog17
-rw-r--r--gcc/c-family/c-attribs.c110
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/c-family/c-ubsan.c22
-rw-r--r--gcc/c-family/c-ubsan.h3
-rw-r--r--gcc/c/ChangeLog9
-rw-r--r--gcc/c/c-convert.c6
-rw-r--r--gcc/c/c-decl.c6
-rw-r--r--gcc/c/c-typeck.c16
-rw-r--r--gcc/common.opt2
-rw-r--r--gcc/convert.c4
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/class.c4
-rw-r--r--gcc/cp/cp-gimplify.c19
-rw-r--r--gcc/cp/cp-ubsan.c3
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/lambda.c4
-rw-r--r--gcc/cp/typeck.c16
-rw-r--r--gcc/doc/extend.texi12
-rw-r--r--gcc/flag-types.h4
-rw-r--r--gcc/gcc.c3
-rw-r--r--gcc/gimple-fold.c3
-rw-r--r--gcc/gimplify.c5
-rw-r--r--gcc/ipa-inline.c11
-rw-r--r--gcc/opts.c35
-rw-r--r--gcc/opts.h2
-rw-r--r--gcc/sanopt.c4
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/attrib-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-4.c42
-rw-r--r--gcc/tree-cfg.c29
-rw-r--r--gcc/tsan.c8
-rw-r--r--gcc/ubsan.c46
-rw-r--r--gcc/ubsan.h1
40 files changed, 409 insertions, 154 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e0a894f..32f2d34 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,36 @@
+2017-06-13 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/78204
+ * asan.c (asan_sanitize_stack_p): Use sanitize_flags_p.
+ (gate_asan): Likewise.
+ * asan.h (asan_no_sanitize_address_p): Remove the function.
+ (sanitize_flags_p): New function.
+ * builtins.def: Fix coding style.
+ * common.opt: Use renamed enum value.
+ * convert.c (convert_to_integer_1): Use sanitize_flags_p.
+ * doc/extend.texi: Document no_sanitize attribute.
+ * flag-types.h (enum sanitize_code): Rename SANITIZE_NONDEFAULT
+ to SANITIZE_UNDEFINED_NONDEFAULT.
+ * gcc.c (sanitize_spec_function): Use the renamed enum value.
+ * gimple-fold.c (optimize_atomic_compare_exchange_p):
+ Use sanitize_flags_p.
+ * gimplify.c (gimplify_function_tree): Likewise.
+ * ipa-inline.c (sanitize_attrs_match_for_inline_p): Likewise.
+ * opts.c (parse_no_sanitize_attribute): New function.
+ (common_handle_option): Use renamed enum value.
+ * opts.h (parse_no_sanitize_attribute): Declare.
+ * tree.c (sanitize_flags_p): New function.
+ * tree.h: Declared here.
+ * tsan.c: Use sanitize_flags_p.
+ * ubsan.c (ubsan_expand_null_ifn): Likewise.
+ (instrument_mem_ref): Likewise.
+ (instrument_bool_enum_load): Likewise.
+ (do_ubsan_in_current_function): Remove the function.
+ (pass_ubsan::execute): Use sanitize_flags_p.
+ * ubsan.h: Remove do_ubsan_in_current_function
+ * tree-cfg.c (print_no_sanitize_attr_value): New function.
+ (dump_function_to_file): Use it here.
+
2017-06-13 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/80803
diff --git a/gcc/asan.c b/gcc/asan.c
index bf564a4..e730530 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -305,9 +305,7 @@ asan_mark_p (gimple *stmt, enum asan_mark_flags flag)
bool
asan_sanitize_stack_p (void)
{
- return ((flag_sanitize & SANITIZE_ADDRESS)
- && ASAN_STACK
- && !asan_no_sanitize_address_p ());
+ return (sanitize_flags_p (SANITIZE_ADDRESS) && ASAN_STACK);
}
/* Checks whether section SEC should be sanitized. */
@@ -3194,9 +3192,7 @@ asan_instrument (void)
static bool
gate_asan (void)
{
- return (flag_sanitize & SANITIZE_ADDRESS) != 0
- && !lookup_attribute ("no_sanitize_address",
- DECL_ATTRIBUTES (current_function_decl));
+ return sanitize_flags_p (SANITIZE_ADDRESS);
}
namespace {
diff --git a/gcc/asan.h b/gcc/asan.h
index 5766397..95bb89e 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -144,13 +144,6 @@ asan_sanitize_use_after_scope (void)
return (flag_sanitize_address_use_after_scope && asan_sanitize_stack_p ());
}
-static inline bool
-asan_no_sanitize_address_p (void)
-{
- return lookup_attribute ("no_sanitize_address",
- DECL_ATTRIBUTES (current_function_decl));
-}
-
/* Return true if DECL should be guarded on the stack. */
static inline bool
@@ -161,4 +154,24 @@ asan_protect_stack_decl (tree decl)
|| (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl)));
}
+/* Return true when flag_sanitize & FLAG is non-zero. If FN is non-null,
+ remove all flags mentioned in "no_sanitize" of DECL_ATTRIBUTES. */
+
+static inline bool
+sanitize_flags_p (unsigned int flag, const_tree fn = current_function_decl)
+{
+ unsigned int result_flags = flag_sanitize & flag;
+ if (result_flags == 0)
+ return false;
+
+ if (fn != NULL_TREE)
+ {
+ tree value = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (fn));
+ if (value)
+ result_flags &= ~tree_to_uhwi (TREE_VALUE (value));
+ }
+
+ return result_flags;
+}
+
#endif /* TREE_ASAN */
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 1c887db..f242137 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -236,7 +236,8 @@ along with GCC; see the file COPYING3. If not see
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
true, true, true, ATTRS, true, \
(flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
- | SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT) \
+ | SANITIZE_UNDEFINED \
+ | SANITIZE_UNDEFINED_NONDEFAULT) \
|| flag_sanitize_coverage))
#undef DEF_CILKPLUS_BUILTIN
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 7ea7781..8488768 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,20 @@
+2017-06-13 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/78204
+ * c-attribs.c (add_no_sanitize_value): New function.
+ (handle_no_sanitize_attribute): Likewise.
+ (handle_no_sanitize_address_attribute): Use the function.
+ (handle_no_sanitize_thread_attribute): New function.
+ (handle_no_address_safety_analysis_attribute): Use
+ add_no_sanitize_value.
+ (handle_no_sanitize_undefined_attribute): Likewise.
+ * c-common.h: Declare new functions.
+ * c-ubsan.c (ubsan_instrument_division): Use sanitize_flags_p.
+ (ubsan_instrument_shift): Likewise.
+ (ubsan_instrument_bounds): Likewise.
+ (ubsan_maybe_instrument_array_ref): Likewise.
+ (ubsan_maybe_instrument_reference_or_call): Likewise.
+
2017-06-11 Jason Merrill <jason@redhat.com>
* c-ada-spec.c, c-pragma.c: Use id_equal.
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 695c58c..2b6845f 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -51,8 +51,11 @@ static tree handle_common_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
+static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
int, bool *);
+static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
+ int, bool *);
static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
int, bool *);
static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
@@ -285,11 +288,14 @@ const struct attribute_spec c_common_attribute_table[] =
0, 0, true, false, false,
handle_no_address_safety_analysis_attribute,
false },
+ { "no_sanitize", 1, 1, true, false, false,
+ handle_no_sanitize_attribute,
+ false },
{ "no_sanitize_address", 0, 0, true, false, false,
handle_no_sanitize_address_attribute,
false },
{ "no_sanitize_thread", 0, 0, true, false, false,
- handle_no_sanitize_address_attribute,
+ handle_no_sanitize_thread_attribute,
false },
{ "no_sanitize_undefined", 0, 0, true, false, false,
handle_no_sanitize_undefined_attribute,
@@ -547,22 +553,98 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
-/* Handle a "no_sanitize_address" attribute; arguments as in
+/* Add FLAGS for a function NODE to no_sanitize_flags in DECL_ATTRIBUTES. */
+
+void
+add_no_sanitize_value (tree node, unsigned int flags)
+{
+ tree attr = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (node));
+ if (attr)
+ {
+ unsigned int old_value = tree_to_uhwi (TREE_VALUE (attr));
+ flags |= old_value;
+
+ if (flags == old_value)
+ return;
+
+ TREE_VALUE (attr) = build_int_cst (unsigned_type_node, flags);
+ }
+ else
+ DECL_ATTRIBUTES (node)
+ = tree_cons (get_identifier ("no_sanitize"),
+ build_int_cst (unsigned_type_node, flags),
+ DECL_ATTRIBUTES (node));
+}
+
+/* Handle a "no_sanitize" attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_no_sanitize_address_attribute (tree *node, tree name, tree, int,
- bool *no_add_attrs)
+handle_no_sanitize_attribute (tree *node, tree name, tree args, int,
+ bool *no_add_attrs)
{
+ *no_add_attrs = true;
+ tree id = TREE_VALUE (args);
if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("no_sanitize argument not a string");
+ return NULL_TREE;
+ }
+
+ char *error_value = NULL;
+ char *string = ASTRDUP (TREE_STRING_POINTER (id));
+ unsigned int flags = parse_no_sanitize_attribute (string, &error_value);
+
+ if (error_value)
+ {
+ error ("wrong argument: \"%s\"", error_value);
+ return NULL_TREE;
}
+ add_no_sanitize_value (*node, flags);
+
+ return NULL_TREE;
+}
+
+/* Handle a "no_sanitize_address" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_sanitize_address_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ else
+ add_no_sanitize_value (*node, SANITIZE_ADDRESS);
+
+ return NULL_TREE;
+}
+
+/* Handle a "no_sanitize_thread" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_sanitize_thread_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ else
+ add_no_sanitize_value (*node, SANITIZE_THREAD);
+
return NULL_TREE;
}
+
/* Handle a "no_address_safety_analysis" attribute; arguments as in
struct attribute_spec.handler. */
@@ -570,13 +652,12 @@ static tree
handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int,
bool *no_add_attrs)
{
+ *no_add_attrs = true;
if (TREE_CODE (*node) != FUNCTION_DECL)
warning (OPT_Wattributes, "%qE attribute ignored", name);
- else if (!lookup_attribute ("no_sanitize_address", DECL_ATTRIBUTES (*node)))
- DECL_ATTRIBUTES (*node)
- = tree_cons (get_identifier ("no_sanitize_address"),
- NULL_TREE, DECL_ATTRIBUTES (*node));
- *no_add_attrs = true;
+ else
+ add_no_sanitize_value (*node, SANITIZE_ADDRESS);
+
return NULL_TREE;
}
@@ -587,11 +668,12 @@ static tree
handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int,
bool *no_add_attrs)
{
+ *no_add_attrs = true;
if (TREE_CODE (*node) != FUNCTION_DECL)
- {
- warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
- }
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ else
+ add_no_sanitize_value (*node,
+ SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
return NULL_TREE;
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 79072e6..1748c19 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1552,6 +1552,7 @@ extern enum flt_eval_method
excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
extern int c_flt_eval_method (bool ts18661_p);
+extern void add_no_sanitize_value (tree node, unsigned int flags);
#if CHECKING_P
namespace selftest {
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index e48841a..a072d19 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -49,11 +49,11 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
op1 = unshare_expr (op1);
if (TREE_CODE (type) == INTEGER_TYPE
- && (flag_sanitize & SANITIZE_DIVIDE))
+ && sanitize_flags_p (SANITIZE_DIVIDE))
t = fold_build2 (EQ_EXPR, boolean_type_node,
op1, build_int_cst (type, 0));
else if (TREE_CODE (type) == REAL_TYPE
- && (flag_sanitize & SANITIZE_FLOAT_DIVIDE))
+ && sanitize_flags_p (SANITIZE_FLOAT_DIVIDE))
t = fold_build2 (EQ_EXPR, boolean_type_node,
op1, build_real (type, dconst0));
else
@@ -61,7 +61,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
/* We check INT_MIN / -1 only for signed types. */
if (TREE_CODE (type) == INTEGER_TYPE
- && (flag_sanitize & SANITIZE_DIVIDE)
+ && sanitize_flags_p (SANITIZE_DIVIDE)
&& !TYPE_UNSIGNED (type))
{
tree x;
@@ -131,7 +131,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
Also punt on bit-fields. */
if (TYPE_OVERFLOW_WRAPS (type0)
|| GET_MODE_BITSIZE (TYPE_MODE (type0)) != TYPE_PRECISION (type0)
- || (flag_sanitize & SANITIZE_SHIFT_BASE) == 0)
+ || !sanitize_flags_p (SANITIZE_SHIFT_BASE))
;
/* For signed x << y, in C99/C11, the following:
@@ -178,7 +178,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
tree else_t = void_node;
if (tt)
{
- if ((flag_sanitize & SANITIZE_SHIFT_EXPONENT) == 0)
+ if (!sanitize_flags_p (SANITIZE_SHIFT_EXPONENT))
{
t = fold_build1 (TRUTH_NOT_EXPR, boolean_type_node, t);
t = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, t, tt);
@@ -301,7 +301,7 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index,
/* Detect flexible array members and suchlike, unless
-fsanitize=bounds-strict. */
tree base = get_base_address (array);
- if ((flag_sanitize & SANITIZE_BOUNDS_STRICT) == 0
+ if (!sanitize_flags_p (SANITIZE_BOUNDS_STRICT)
&& TREE_CODE (array) == COMPONENT_REF
&& base && (INDIRECT_REF_P (base) || TREE_CODE (base) == MEM_REF))
{
@@ -373,7 +373,7 @@ void
ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one)
{
if (!ubsan_array_ref_instrumented_p (*expr_p)
- && do_ubsan_in_current_function ())
+ && sanitize_flags_p (SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT))
{
tree op0 = TREE_OPERAND (*expr_p, 0);
tree op1 = TREE_OPERAND (*expr_p, 1);
@@ -393,7 +393,7 @@ static tree
ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
enum ubsan_null_ckind ckind)
{
- if (!do_ubsan_in_current_function ())
+ if (!sanitize_flags_p (SANITIZE_ALIGNMENT | SANITIZE_NULL))
return NULL_TREE;
tree type = TREE_TYPE (ptype);
@@ -401,7 +401,7 @@ ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
bool instrument = false;
unsigned int mina = 0;
- if (flag_sanitize & SANITIZE_ALIGNMENT)
+ if (sanitize_flags_p (SANITIZE_ALIGNMENT))
{
mina = min_align_of_type (type);
if (mina <= 1)
@@ -419,7 +419,7 @@ ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
}
else
{
- if ((flag_sanitize & SANITIZE_NULL) && TREE_CODE (op) == ADDR_EXPR)
+ if (sanitize_flags_p (SANITIZE_NULL) && TREE_CODE (op) == ADDR_EXPR)
{
bool strict_overflow_p = false;
/* tree_single_nonzero_warnv_p will not return true for non-weak
@@ -435,7 +435,7 @@ ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks;
}
- else if (flag_sanitize & SANITIZE_NULL)
+ else if (sanitize_flags_p (SANITIZE_NULL))
instrument = true;
if (mina && mina > 1)
{
diff --git a/gcc/c-family/c-ubsan.h b/gcc/c-family/c-ubsan.h
index 3c3ffc7..1e2d192 100644
--- a/gcc/c-family/c-ubsan.h
+++ b/gcc/c-family/c-ubsan.h
@@ -31,7 +31,4 @@ extern void ubsan_maybe_instrument_array_ref (tree *, bool);
extern void ubsan_maybe_instrument_reference (tree *);
extern void ubsan_maybe_instrument_member_call (tree, bool);
-/* Declare this here as well as in ubsan.h. */
-extern bool do_ubsan_in_current_function (void);
-
#endif /* GCC_C_UBSAN_H */
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index e94bcea..173fa92 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,12 @@
+2017-06-13 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/78204
+ * c-convert.c (convert): Use sanitize_flags_p.
+ * c-decl.c (grokdeclarator): Likewise.
+ * c-typeck.c (convert_for_assignment): Likewise.
+ (c_finish_return): Likewise.
+ (build_binary_op): Likewise.
+
2017-06-08 Jakub Jelinek <jakub@redhat.com>
PR c/81006
diff --git a/gcc/c/c-convert.c b/gcc/c/c-convert.c
index b8117b4..33c9143 100644
--- a/gcc/c/c-convert.c
+++ b/gcc/c/c-convert.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "convert.h"
#include "langhooks.h"
#include "ubsan.h"
+#include "asan.h"
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
@@ -106,10 +107,9 @@ convert (tree type, tree expr)
case INTEGER_TYPE:
case ENUMERAL_TYPE:
- if (flag_sanitize & SANITIZE_FLOAT_CAST
+ if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
&& TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
- && COMPLETE_TYPE_P (type)
- && do_ubsan_in_current_function ())
+ && COMPLETE_TYPE_P (type))
{
expr = save_expr (expr);
tree check = ubsan_instrument_float_cast (loc, type, expr);
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3a0a4f5..317d5cd 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "spellcheck-tree.h"
#include "gcc-rich-location.h"
+#include "asan.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -6044,9 +6045,8 @@ grokdeclarator (const struct c_declarator *declarator,
with known value. */
this_size_varies = size_varies = true;
warn_variable_length_array (name, size);
- if (flag_sanitize & SANITIZE_VLA
- && decl_context == NORMAL
- && do_ubsan_in_current_function ())
+ if (sanitize_flags_p (SANITIZE_VLA)
+ && decl_context == NORMAL)
{
/* Evaluate the array size only once. */
size = save_expr (size);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index ba44406..4d067e9 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "gomp-constants.h"
#include "spellcheck-tree.h"
#include "gcc-rich-location.h"
+#include "asan.h"
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
@@ -6378,7 +6379,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE
|| (coder == REAL_TYPE
&& (codel == INTEGER_TYPE || codel == ENUMERAL_TYPE)
- && (flag_sanitize & SANITIZE_FLOAT_CAST)))
+ && sanitize_flags_p (SANITIZE_FLOAT_CAST)))
in_late_binary_op = true;
ret = convert_and_check (expr_loc != UNKNOWN_LOCATION
? expr_loc : location, type, orig_rhs);
@@ -9955,7 +9956,7 @@ c_finish_return (location_t loc, tree retval, tree origtype)
|| (TREE_CODE (TREE_TYPE (t)) == REAL_TYPE
&& (TREE_CODE (TREE_TYPE (res)) == INTEGER_TYPE
|| TREE_CODE (TREE_TYPE (res)) == ENUMERAL_TYPE)
- && (flag_sanitize & SANITIZE_FLOAT_CAST)))
+ && sanitize_flags_p (SANITIZE_FLOAT_CAST)))
in_late_binary_op = true;
inner = t = convert (TREE_TYPE (res), t);
in_late_binary_op = save;
@@ -11835,9 +11836,8 @@ build_binary_op (location_t location, enum tree_code code,
return error_mark_node;
}
- if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE
- | SANITIZE_FLOAT_DIVIDE))
- && do_ubsan_in_current_function ()
+ if (sanitize_flags_p ((SANITIZE_SHIFT
+ | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
&& (doing_div_or_mod || doing_shift)
&& !require_constant_value)
{
@@ -11846,10 +11846,10 @@ build_binary_op (location_t location, enum tree_code code,
op1 = save_expr (op1);
op0 = c_fully_fold (op0, false, NULL);
op1 = c_fully_fold (op1, false, NULL);
- if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE
- | SANITIZE_FLOAT_DIVIDE)))
+ if (doing_div_or_mod && (sanitize_flags_p ((SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE))))
instrument_expr = ubsan_instrument_division (location, op0, op1);
- else if (doing_shift && (flag_sanitize & SANITIZE_SHIFT))
+ else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT))
instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
}
diff --git a/gcc/common.opt b/gcc/common.opt
index 0a10511..4f9c3dc 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -224,7 +224,7 @@ unsigned int flag_sanitize
; What sanitizers should recover from errors
Variable
-unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT | SANITIZE_KERNEL_ADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)
+unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT | SANITIZE_KERNEL_ADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)
fsanitize-coverage=trace-pc
Common Report Var(flag_sanitize_coverage)
diff --git a/gcc/convert.c b/gcc/convert.c
index af8dfda..429f988 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "builtins.h"
#include "ubsan.h"
+#include "asan.h"
#define maybe_fold_build1_loc(FOLD_P, LOC, CODE, TYPE, EXPR) \
((FOLD_P) ? fold_build1_loc (LOC, CODE, TYPE, EXPR) \
@@ -937,8 +938,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
return build1 (CONVERT_EXPR, type, expr);
case REAL_TYPE:
- if (flag_sanitize & SANITIZE_FLOAT_CAST
- && do_ubsan_in_current_function ())
+ if (sanitize_flags_p (SANITIZE_FLOAT_CAST))
{
expr = save_expr (expr);
tree check = ubsan_instrument_float_cast (loc, type, expr);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6d2f28b..4388830 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+2017-06-13 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/78204
+ * class.c (build_base_path): Use sanitize_flags_p.
+ * cp-gimplify.c (cp_genericize_r): Likewise.
+ (cp_genericize_tree): Likewise.
+ (cp_genericize): Likewise.
+ * cp-ubsan.c (cp_ubsan_instrument_vptr_p): Likewise.
+ * decl.c (compute_array_index_type): Likewise.
+ (start_preparsed_function): Likewise.
+ * decl2.c (one_static_initialization_or_destruction): Likewise.
+ * init.c (finish_length_check): Likewise.
+ * lambda.c (maybe_add_lambda_conv_op): Likewise.
+ * typeck.c (cp_build_binary_op): Likewise.
+ (build_static_cast_1): Likewise.
+
2017-06-11 Jason Merrill <jason@redhat.com>
* error.c (dump_expr): Use is_this_parameter.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 66f4262..dd1051e 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
#include "gimplify.h"
#include "intl.h"
+#include "asan.h"
/* Id for dumping the class hierarchy. */
int class_dump_id;
@@ -462,7 +463,8 @@ build_base_path (enum tree_code code,
else
{
tree t = expr;
- if ((flag_sanitize & SANITIZE_VPTR) && fixed_type_p == 0)
+ if (sanitize_flags_p (SANITIZE_VPTR)
+ && fixed_type_p == 0)
{
t = cp_ubsan_maybe_instrument_cast_to_vbase (input_location,
probe, expr);
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index e3802f1..3c8f4b0 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-ubsan.h"
#include "cilk.h"
#include "cp-cilkplus.h"
+#include "asan.h"
/* Forward declarations. */
@@ -1262,8 +1263,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
: OMP_CLAUSE_DEFAULT_PRIVATE);
}
}
- if (flag_sanitize
- & (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
+ if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
{
/* The point here is to not sanitize static initializers. */
bool no_sanitize_p = wtd->no_sanitize_p;
@@ -1450,11 +1450,11 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
*stmt_p = cplus_expand_constant (stmt);
*walk_subtrees = 0;
}
- else if ((flag_sanitize
- & (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
+ else if (sanitize_flags_p ((SANITIZE_NULL
+ | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
&& !wtd->no_sanitize_p)
{
- if ((flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
+ if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT)
&& TREE_CODE (stmt) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE)
ubsan_maybe_instrument_reference (stmt_p);
@@ -1470,9 +1470,9 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
= TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0));
- if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
+ if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT))
ubsan_maybe_instrument_member_call (stmt, is_ctor);
- if ((flag_sanitize & SANITIZE_VPTR) && !is_ctor)
+ if (sanitize_flags_p (SANITIZE_VPTR) && !is_ctor)
cp_ubsan_maybe_instrument_member_call (stmt);
}
}
@@ -1499,7 +1499,7 @@ cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p)
cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
delete wtd.p_set;
wtd.bind_expr_stack.release ();
- if (flag_sanitize & SANITIZE_VPTR)
+ if (sanitize_flags_p (SANITIZE_VPTR))
cp_ubsan_instrument_member_accesses (t_p);
}
@@ -1622,8 +1622,7 @@ cp_genericize (tree fndecl)
walk_tree's hash functionality. */
cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true);
- if (flag_sanitize & SANITIZE_RETURN
- && do_ubsan_in_current_function ())
+ if (sanitize_flags_p (SANITIZE_RETURN))
cp_ubsan_maybe_instrument_return (fndecl);
/* Do everything else. */
diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c
index 71d315e..f00f870 100644
--- a/gcc/cp/cp-ubsan.c
+++ b/gcc/cp/cp-ubsan.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "cp-tree.h"
#include "ubsan.h"
+#include "asan.h"
/* Test if we should instrument vptr access. */
@@ -32,7 +33,7 @@ cp_ubsan_instrument_vptr_p (tree type)
if (!flag_rtti || flag_sanitize_undefined_trap_on_error)
return false;
- if (!do_ubsan_in_current_function ())
+ if (!sanitize_flags_p (SANITIZE_VPTR))
return false;
if (type)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b0df3c9..3711476 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "cilk.h"
#include "builtins.h"
#include "gimplify.h"
+#include "asan.h"
/* Possible cases of bad specifiers type used by bad_specifiers. */
enum bad_spec_place {
@@ -9524,8 +9525,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
stabilize_vla_size (itype);
- if (flag_sanitize & SANITIZE_VLA
- && do_ubsan_in_current_function ())
+ if (sanitize_flags_p (SANITIZE_VLA))
{
/* We have to add 1 -- in the ubsan routine we generate
LE_EXPR rather than LT_EXPR. */
@@ -15108,7 +15108,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
if (!processing_template_decl
&& DECL_CONSTRUCTOR_P (decl1)
- && (flag_sanitize & SANITIZE_VPTR)
+ && sanitize_flags_p (SANITIZE_VPTR)
&& !DECL_CLONED_FUNCTION_P (decl1)
&& !implicit_default_ctor_p (decl1))
cp_ubsan_maybe_initialize_vtbl_ptrs (current_class_ptr);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d3d9002..ab32b71 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3737,7 +3737,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
if (init)
{
finish_expr_stmt (init);
- if (flag_sanitize & SANITIZE_ADDRESS)
+ if (sanitize_flags_p (SANITIZE_ADDRESS, decl))
{
varpool_node *vnode = varpool_node::get (decl);
if (vnode)
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 4ad2cae..90abd23 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "c-family/c-ubsan.h"
#include "intl.h"
+#include "asan.h"
static bool begin_init_stmts (tree *, tree *);
static tree finish_init_stmts (bool, tree, tree);
@@ -3911,8 +3912,7 @@ finish_length_check (tree atype, tree iterator, tree obase, unsigned n)
}
/* Don't check an array new when -fno-exceptions. */
}
- else if (flag_sanitize & SANITIZE_BOUNDS
- && do_ubsan_in_current_function ())
+ else if (sanitize_flags_p (SANITIZE_BOUNDS))
{
/* Make sure the last element of the initializer is in bounds. */
finish_expr_stmt
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 5587f60..52e1fb7 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -1150,9 +1150,7 @@ maybe_add_lambda_conv_op (tree type)
{
/* Don't UBsan this function; we're deliberately calling op() with a null
object argument. */
- tree attrs = build_tree_list (get_identifier ("no_sanitize_undefined"),
- NULL_TREE);
- cplus_decl_attributes (&fn, attrs, 0);
+ add_no_sanitize_value (fn, SANITIZE_UNDEFINED);
}
add_method (type, fn, false);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 34d475b..05b4fbb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-ubsan.h"
#include "params.h"
#include "gcc-rich-location.h"
+#include "asan.h"
static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
static tree cp_build_function_call (tree, tree, tsubst_flags_t);
@@ -5253,10 +5254,9 @@ cp_build_binary_op (location_t location,
if (build_type == NULL_TREE)
build_type = result_type;
- if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE
- | SANITIZE_FLOAT_DIVIDE))
+ if (sanitize_flags_p ((SANITIZE_SHIFT
+ | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
&& !processing_template_decl
- && do_ubsan_in_current_function ()
&& (doing_div_or_mod || doing_shift))
{
/* OP0 and/or OP1 might have side-effects. */
@@ -5264,8 +5264,8 @@ cp_build_binary_op (location_t location,
op1 = cp_save_expr (op1);
op0 = fold_non_dependent_expr (op0);
op1 = fold_non_dependent_expr (op1);
- if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE
- | SANITIZE_FLOAT_DIVIDE)))
+ if (doing_div_or_mod
+ && sanitize_flags_p (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
{
/* For diagnostics we want to use the promoted types without
shorten_binary_op. So convert the arguments to the
@@ -5278,7 +5278,7 @@ cp_build_binary_op (location_t location,
cop1 = cp_convert (orig_type, op1, complain);
instrument_expr = ubsan_instrument_division (location, cop0, cop1);
}
- else if (doing_shift && (flag_sanitize & SANITIZE_SHIFT))
+ else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT))
instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
}
@@ -6823,7 +6823,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
NULL, complain);
expr = build_address (expr);
- if (flag_sanitize & SANITIZE_VPTR)
+ if (sanitize_flags_p (SANITIZE_VPTR))
{
tree ubsan_check
= cp_ubsan_maybe_instrument_downcast (input_location, type,
@@ -6967,7 +6967,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
complain);
- if (flag_sanitize & SANITIZE_VPTR)
+ if (sanitize_flags_p (SANITIZE_VPTR))
{
tree ubsan_check
= cp_ubsan_maybe_instrument_downcast (input_location, type,
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ef1ae73..1de17b4 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2911,6 +2911,18 @@ This has a similar effect
as the @option{-fno-toplevel-reorder} option, but only applies to the
marked symbols.
+@item no_sanitize ("@var{sanitize_option}")
+@cindex @code{no_sanitize} function attribute
+The @code{no_sanitize} attribute on functions is used
+to inform the compiler that it should not do sanitization of all options
+mentioned in @var{sanitize_option}. A list of values acceptable by
+@option{-fsanitize} option can be provided.
+
+@smallexample
+void __attribute__ ((no_sanitize ("alignment", "object-size")))
+f () @{ /* @r{Do something.} */; @}
+@end smallexample
+
@item no_sanitize_address
@itemx no_address_safety_analysis
@cindex @code{no_sanitize_address} function attribute
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 27a38ef..5faade5 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -246,8 +246,8 @@ enum sanitize_code {
| SANITIZE_NONNULL_ATTRIBUTE
| SANITIZE_RETURNS_NONNULL_ATTRIBUTE
| SANITIZE_OBJECT_SIZE | SANITIZE_VPTR,
- SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
- | SANITIZE_BOUNDS_STRICT
+ SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
+ | SANITIZE_BOUNDS_STRICT
};
/* flag_vtable_verify initialization levels. */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 4724276..3292532 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -9398,7 +9398,8 @@ sanitize_spec_function (int argc, const char **argv)
if (strcmp (argv[0], "thread") == 0)
return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
if (strcmp (argv[0], "undefined") == 0)
- return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+ return ((flag_sanitize
+ & (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT))
&& !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
if (strcmp (argv[0], "leak") == 0)
return ((flag_sanitize
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index d12f9d0..0f8e326 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-chkp.h"
#include "tree-cfg.h"
#include "fold-const-call.h"
+#include "asan.h"
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -3479,7 +3480,7 @@ optimize_atomic_compare_exchange_p (gimple *stmt)
if (gimple_call_num_args (stmt) != 6
|| !flag_inline_atomics
|| !optimize
- || (flag_sanitize & (SANITIZE_THREAD | SANITIZE_ADDRESS)) != 0
+ || sanitize_flags_p (SANITIZE_THREAD | SANITIZE_ADDRESS)
|| !gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
|| !gimple_vdef (stmt)
|| !gimple_vuse (stmt))
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 653057f..9af95a2 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -12647,7 +12647,7 @@ gimplify_function_tree (tree fndecl)
&& !needs_to_live_in_memory (ret))
DECL_GIMPLE_REG_P (ret) = 1;
- if (asan_sanitize_use_after_scope () && !asan_no_sanitize_address_p ())
+ if (asan_sanitize_use_after_scope () && sanitize_flags_p (SANITIZE_ADDRESS))
asan_poisoned_variables = new hash_set<tree> ();
bind = gimplify_body (fndecl, true);
if (asan_poisoned_variables)
@@ -12714,8 +12714,7 @@ gimplify_function_tree (tree fndecl)
bind = new_bind;
}
- if ((flag_sanitize & SANITIZE_THREAD) != 0
- && !lookup_attribute ("no_sanitize_thread", DECL_ATTRIBUTES (fndecl)))
+ if (sanitize_flags_p (SANITIZE_THREAD))
{
gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 8924f7e..fb20d37 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -117,6 +117,7 @@ along with GCC; see the file COPYING3. If not see
#include "auto-profile.h"
#include "builtins.h"
#include "fibonacci_heap.h"
+#include "asan.h"
typedef fibonacci_heap <sreal, cgraph_edge> edge_heap_t;
typedef fibonacci_node <sreal, cgraph_edge> edge_heap_node_t;
@@ -257,17 +258,11 @@ report_inline_failed_reason (struct cgraph_edge *e)
static bool
sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee)
{
- /* Don't care if sanitizer is disabled */
- if (!(flag_sanitize & SANITIZE_ADDRESS))
- return true;
-
if (!caller || !callee)
return true;
- return !!lookup_attribute ("no_sanitize_address",
- DECL_ATTRIBUTES (caller)) ==
- !!lookup_attribute ("no_sanitize_address",
- DECL_ATTRIBUTES (callee));
+ return sanitize_flags_p (SANITIZE_ADDRESS, caller)
+ == sanitize_flags_p (SANITIZE_ADDRESS, callee);
}
/* Used for flags where it is safe to inline when caller's value is
diff --git a/gcc/opts.c b/gcc/opts.c
index 60ebe56..4013ea5 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1656,6 +1656,37 @@ parse_sanitizer_options (const char *p, location_t loc, int scode,
return flags;
}
+/* Parse string values of no_sanitize attribute passed in VALUE.
+ Values are separated with comma. Wrong argument is stored to
+ WRONG_ARGUMENT variable. */
+
+unsigned int
+parse_no_sanitize_attribute (char *value, char **wrong_argument)
+{
+ unsigned int flags = 0;
+ unsigned int i;
+ char *q = strtok (value, ",");
+
+ while (q != NULL)
+ {
+ for (i = 0; sanitizer_opts[i].name != NULL; ++i)
+ if (strcmp (sanitizer_opts[i].name, q) == 0)
+ {
+ flags |= sanitizer_opts[i].flag;
+ if (sanitizer_opts[i].flag == SANITIZE_UNDEFINED)
+ flags |= SANITIZE_UNDEFINED_NONDEFAULT;
+ break;
+ }
+
+ if (sanitizer_opts[i].name == NULL)
+ *wrong_argument = q;
+
+ q = strtok (NULL, ",");
+ }
+
+ return flags;
+}
+
/* Handle target- and language-independent options. Return zero to
generate an "unknown option" message. Only options that need
extra handling need to be listed here; if you simply want
@@ -1892,11 +1923,11 @@ common_handle_option (struct gcc_options *opts,
case OPT_fsanitize_recover:
if (value)
opts->x_flag_sanitize_recover
- |= (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)
+ |= (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT)
& ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN);
else
opts->x_flag_sanitize_recover
- &= ~(SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT);
+ &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
break;
case OPT_O:
diff --git a/gcc/opts.h b/gcc/opts.h
index eb626aa..16371e8 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -378,6 +378,8 @@ extern void print_ignored_options (void);
extern void handle_common_deferred_options (void);
unsigned int parse_sanitizer_options (const char *, location_t, int,
unsigned int, int, bool);
+
+unsigned int parse_no_sanitize_attribute (char *value, char **wrong_argument);
extern bool common_handle_option (struct gcc_options *opts,
struct gcc_options *opts_set,
const struct cl_decoded_option *decoded,
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 70b7aeb..16bdba7 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -948,9 +948,7 @@ pass_sanopt::execute (function *fun)
switch (DECL_FUNCTION_CODE (callee))
{
case BUILT_IN_UNREACHABLE:
- if (flag_sanitize & SANITIZE_UNREACHABLE
- && !lookup_attribute ("no_sanitize_undefined",
- DECL_ATTRIBUTES (fun->decl)))
+ if (sanitize_flags_p (SANITIZE_UNREACHABLE))
no_next = ubsan_instrument_unreachable (&gsi);
break;
default:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6b33a67..1eddf49 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2017-06-13 Martin Liska <mliska@suse.cz>
+
+ PR sanitize/78204
+ * c-c++-common/ubsan/attrib-2.c (float_cast2): Enhance the
+ test by adding no_sanitize attribute.
+ * gcc.dg/asan/use-after-scope-4.c: Likewise.
+
2017-06-13 Renlin Li <renlin.li@arm.com>
* gcc.target/arm/cold-lc.c: Update coding style, call dump_stack
diff --git a/gcc/testsuite/c-c++-common/ubsan/attrib-2.c b/gcc/testsuite/c-c++-common/ubsan/attrib-2.c
index 71f2e58..3f0a9c3 100644
--- a/gcc/testsuite/c-c++-common/ubsan/attrib-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/attrib-2.c
@@ -68,4 +68,14 @@ float_cast (void)
c = d;
}
+__attribute__((no_sanitize(("undefined"))))
+static void
+float_cast2 (void)
+{
+ volatile double d = 300;
+ volatile signed char c;
+ c = d;
+}
+
+
/* { dg-final { scan-assembler-not "__ubsan_handle" } } */
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
index 77d7052..44dc795 100644
--- a/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
@@ -1,16 +1,40 @@
// { dg-do run }
-int
+#define FN(NAME) \
+NAME (void) \
+{ \
+ char *ptr; \
+ char *ptr2; \
+ { \
+ char my_char[9]; \
+ ptr = &my_char[0]; \
+ __builtin_memcpy (&ptr2, &ptr, sizeof (ptr2)); \
+ } \
+ \
+ *(ptr2+9) = 'c'; \
+}
+
+void
+__attribute__((no_sanitize(("address"))))
+__attribute__((no_sanitize(("undefined"))))
+__attribute__((no_sanitize(("address"))))
+__attribute__((no_sanitize(("null"))))
+FN (fn1)
+
+void
+__attribute__((no_sanitize(("all"))))
+FN (fn2)
+
+void
__attribute__((no_sanitize_address))
+FN (fn3)
+
+int
main (void)
{
- char *ptr;
- char *ptr2;
- {
- char my_char[9];
- ptr = &my_char[0];
- __builtin_memcpy (&ptr2, &ptr, sizeof (ptr2));
- }
+ fn1 ();
+ fn2 ();
+ fn3 ();
- *(ptr2+9) = 'c';
+ return 0;
}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index c84e99d..7df80f8 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "attribs.h"
#include "selftest.h"
+#include "opts.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
@@ -7555,6 +7556,25 @@ dump_default_def (FILE *file, tree def, int spc, dump_flags_t flags)
fprintf (file, ";\n");
}
+/* Print no_sanitize attribute to FILE for a given attribute VALUE. */
+
+static void
+print_no_sanitize_attr_value (FILE *file, tree value)
+{
+ unsigned int flags = tree_to_uhwi (value);
+ bool first = true;
+ for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
+ {
+ if ((sanitizer_opts[i].flag & flags) == sanitizer_opts[i].flag)
+ {
+ if (!first)
+ fprintf (file, " | ");
+ fprintf (file, "%s", sanitizer_opts[i].name);
+ first = false;
+ }
+ }
+}
+
/* Dump FUNCTION_DECL FN to file FILE using FLAGS (see TDF_* in dumpfile.h)
*/
@@ -7582,11 +7602,16 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags)
if (!first)
fprintf (file, ", ");
- print_generic_expr (file, get_attribute_name (chain), dump_flags);
+ tree name = get_attribute_name (chain);
+ print_generic_expr (file, name, dump_flags);
if (TREE_VALUE (chain) != NULL_TREE)
{
fprintf (file, " (");
- print_generic_expr (file, TREE_VALUE (chain), dump_flags);
+
+ if (strstr (IDENTIFIER_POINTER (name), "no_sanitize"))
+ print_no_sanitize_attr_value (file, TREE_VALUE (chain));
+ else
+ print_generic_expr (file, TREE_VALUE (chain), dump_flags);
fprintf (file, ")");
}
}
diff --git a/gcc/tsan.c b/gcc/tsan.c
index dd8cd85..2f98b93 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -896,9 +896,7 @@ public:
opt_pass * clone () { return new pass_tsan (m_ctxt); }
virtual bool gate (function *)
{
- return ((flag_sanitize & SANITIZE_THREAD) != 0
- && !lookup_attribute ("no_sanitize_thread",
- DECL_ATTRIBUTES (current_function_decl)));
+ return sanitize_flags_p (SANITIZE_THREAD);
}
virtual unsigned int execute (function *) { return tsan_pass (); }
@@ -938,9 +936,7 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
- return ((flag_sanitize & SANITIZE_THREAD) != 0 && !optimize
- && !lookup_attribute ("no_sanitize_thread",
- DECL_ATTRIBUTES (current_function_decl)));
+ return (sanitize_flags_p (SANITIZE_THREAD) && !optimize);
}
virtual unsigned int execute (function *) { return tsan_pass (); }
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 133409a..cee525c 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -757,7 +757,7 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
gsi_insert_before (&gsi, g, GSI_SAME_STMT);
}
}
- check_null = (flag_sanitize & SANITIZE_NULL) != 0;
+ check_null = sanitize_flags_p (SANITIZE_NULL);
if (check_align == NULL_TREE && !check_null)
{
@@ -1181,13 +1181,13 @@ instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
{
enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
unsigned int align = 0;
- if (flag_sanitize & SANITIZE_ALIGNMENT)
+ if (sanitize_flags_p (SANITIZE_ALIGNMENT))
{
align = min_align_of_type (TREE_TYPE (base));
if (align <= 1)
align = 0;
}
- if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
+ if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
return;
tree t = TREE_OPERAND (base, 0);
if (!POINTER_TYPE_P (TREE_TYPE (t)))
@@ -1355,13 +1355,14 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
tree type = TREE_TYPE (rhs);
tree minv = NULL_TREE, maxv = NULL_TREE;
- if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
+ if (TREE_CODE (type) == BOOLEAN_TYPE
+ && sanitize_flags_p (SANITIZE_BOOL))
{
minv = boolean_false_node;
maxv = boolean_true_node;
}
else if (TREE_CODE (type) == ENUMERAL_TYPE
- && (flag_sanitize & SANITIZE_ENUM)
+ && sanitize_flags_p (SANITIZE_ENUM)
&& TREE_TYPE (type) != NULL_TREE
&& TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (type))
@@ -1924,16 +1925,6 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
gsi_insert_before (gsi, g, GSI_SAME_STMT);
}
-/* True if we want to play UBSan games in the current function. */
-
-bool
-do_ubsan_in_current_function ()
-{
- return (current_function_decl != NULL_TREE
- && !lookup_attribute ("no_sanitize_undefined",
- DECL_ATTRIBUTES (current_function_decl)));
-}
-
namespace {
const pass_data pass_data_ubsan =
@@ -1959,13 +1950,12 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
- return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
- | SANITIZE_BOOL | SANITIZE_ENUM
- | SANITIZE_ALIGNMENT
- | SANITIZE_NONNULL_ATTRIBUTE
- | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
- | SANITIZE_OBJECT_SIZE)
- && do_ubsan_in_current_function ();
+ return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
+ | SANITIZE_BOOL | SANITIZE_ENUM
+ | SANITIZE_ALIGNMENT
+ | SANITIZE_NONNULL_ATTRIBUTE
+ | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
+ | SANITIZE_OBJECT_SIZE));
}
virtual unsigned int execute (function *);
@@ -1992,11 +1982,11 @@ pass_ubsan::execute (function *fun)
continue;
}
- if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
+ if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
&& is_gimple_assign (stmt))
instrument_si_overflow (gsi);
- if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
+ if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
{
if (gimple_store_p (stmt))
instrument_null (gsi, true);
@@ -2018,14 +2008,14 @@ pass_ubsan::execute (function *fun)
}
}
- if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
+ if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
&& gimple_assign_load_p (stmt))
{
instrument_bool_enum_load (&gsi);
bb = gimple_bb (stmt);
}
- if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
+ if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
&& is_gimple_call (stmt)
&& !gimple_call_internal_p (stmt))
{
@@ -2033,14 +2023,14 @@ pass_ubsan::execute (function *fun)
bb = gimple_bb (stmt);
}
- if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
+ if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
&& gimple_code (stmt) == GIMPLE_RETURN)
{
instrument_nonnull_return (&gsi);
bb = gimple_bb (stmt);
}
- if (flag_sanitize & SANITIZE_OBJECT_SIZE)
+ if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
{
if (gimple_store_p (stmt))
instrument_object_size (&gsi, true);
diff --git a/gcc/ubsan.h b/gcc/ubsan.h
index f04929d..fddd359 100644
--- a/gcc/ubsan.h
+++ b/gcc/ubsan.h
@@ -42,7 +42,6 @@ enum ubsan_print_style {
UBSAN_PRINT_ARRAY
};
-extern bool do_ubsan_in_current_function (void);
extern bool ubsan_expand_bounds_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_null_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_objsize_ifn (gimple_stmt_iterator *);