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

Reply via email to