Hi! Ok, first let me list some needed follow-ups that don't need to be handled right away: - r237814-like changes for ASAN_MARK - optimization to remove ASAN_MARK unpoisoning at the start of the function - optimization to remove ASAN_MARK poisoning at the end of function (and remove epilogue unpoisoning) - optimization to remove ASAN_MARK unpoisoning followed by ASAN_MARK poisoning or vice versa if there are no memory accesses in between - try to improve the goto handling
On Mon, Oct 03, 2016 at 11:27:38AM +0200, Martin Liška wrote: > + if (dump_file && (dump_flags & TDF_DETAILS)) > + fprintf (dump_file, "Skipping stack emission for variable: %s " > + "(%ldB)\n", This message is weird. I would have thought you are informing the user that you are unpoisoning the stack for the specified variable. > + IDENTIFIER_POINTER (DECL_NAME (decl)), Can't DECL_NAME be NULL? > + var_end_offset - var_offset); > + for (unsigned i = 0; i < size; ++i) > + { > + unsigned char shadow_c = c; > + if (i == size- 1 && last_chunk_size && !is_clobber) Wrong formatting, space before - missing. > + g = gimple_build_assign (make_ssa_name (pointer_sized_int_node), > + NOP_EXPR, base); Incorrect indentation. > + > +/* Return TRUE if we should instrument for use-after-scope sanity checking. > */ > + > +static inline bool > +asan_sanitize_use_after_scope (void) > +{ > + return ((flag_sanitize & SANITIZE_ADDRESS_USE_AFTER_SCOPE) > + == SANITIZE_ADDRESS_USE_AFTER_SCOPE > + && ASAN_STACK); > +} This looks wrong. IMHO you really don't want to use ASAN_STACK in asan.h, because it requires params.h. I think what would be best is to prototype asan_sanitize_stack_p in asan.h, remove static inline from its definition, and have asan.h static inline bool asan_sanitize_use_after_scope (void) { return (flag_sanitize_use_after_scope && asan_sanitize_stack_p (); } That way, for the common case of no sanitization it would be inline and fast. > +static inline bool > +asan_no_sanitize_address_p (void) > +{ > + return lookup_attribute ("no_sanitize_address", > + DECL_ATTRIBUTES (current_function_decl)); > +} And you could avoid doing this. > + if ((asan_sanitize_stack_p () || asan_sanitize_use_after_scope ()) And then just drop asan_sanitize_use_after_scope () from cases like this, because really asan_sanitize_use_after_scope () must imply asan_sanitize_stack_p (). > @@ -1127,7 +1127,8 @@ expand_stack_vars (bool (*pred) (size_t), struct > stack_vars_data *data) > if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) > { > base = virtual_stack_vars_rtx; > - if (asan_sanitize_stack_p () && pred) > + if ((asan_sanitize_stack_p () || asan_sanitize_use_after_scope ()) Likewise. > + && pred) > @@ -1514,7 +1515,9 @@ defer_stack_allocation (tree var, bool toplevel) > /* If stack protection is enabled, *all* stack variables must be deferred, > so that we can re-order the strings to the top of the frame. > Similarly for Address Sanitizer. */ > - if (flag_stack_protect || asan_sanitize_stack_p ()) > + if (flag_stack_protect > + || asan_sanitize_stack_p () > + || asan_sanitize_use_after_scope ()) And again. > return true; > > unsigned int align = TREE_CODE (var) == SSA_NAME > @@ -2212,7 +2215,7 @@ expand_used_vars (void) > expand_stack_vars (stack_protect_decl_phase_2, &data); > } > > - if (asan_sanitize_stack_p ()) > + if (asan_sanitize_stack_p () || asan_sanitize_use_after_scope ()) And again. > --- a/gcc/flag-types.h > +++ b/gcc/flag-types.h > @@ -229,6 +229,7 @@ enum sanitize_code { > SANITIZE_OBJECT_SIZE = 1UL << 20, > SANITIZE_VPTR = 1UL << 21, > SANITIZE_BOUNDS_STRICT = 1UL << 22, > + SANITIZE_USE_AFTER_SCOPE = 1UL << 23, > SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | > SANITIZE_UNREACHABLE > | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN > | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM > @@ -237,7 +238,9 @@ enum sanitize_code { > | SANITIZE_RETURNS_NONNULL_ATTRIBUTE > | SANITIZE_OBJECT_SIZE | SANITIZE_VPTR, > SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST > - | SANITIZE_BOUNDS_STRICT > + | SANITIZE_BOUNDS_STRICT, > + SANITIZE_ADDRESS_USE_AFTER_SCOPE = SANITIZE_ADDRESS > + | SANITIZE_USE_AFTER_SCOPE Looking at this, as -fsanitize-use-after-scope is a separate option, it shouldn't mess up anything in the SANITIZE_* flags. So just use a flag_sanitize_use_after_scope var for that. It isn't something where you'd decide differently on it e.g. for -fno-sanitize= of -fsanitize-recover= etc. > @@ -1228,6 +1306,14 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) > } > } > } > + > + if (asan_sanitize_use_after_scope () > + && asan_poisoned_variables != NULL > + && asan_poisoned_variables->contains (t)) Do you really need the asan_sanitize_use_after_scope () ? Won't the hash_set not be populated at all if it isn't true? > + if (asan_sanitize_use_after_scope () > + && !asan_no_sanitize_address_p () You wouldn't need to check !asan_no_sanitize_address_p () separately here. Jakub