On Wed, 19 Nov 2014, Marek Polacek wrote:

> The problem here is that negate_expr_p returns true (as it should)
> for UINT_MAX(OVF), but fold_negate_expr didn't actually fold it,
> and that is a no-no; if negate_expr_p is true, fold_negate_expr must
> not return NULL_TREE.  I added the following hunk for bootstrap and
> regtest for better coverage:
> 
> @@ -752,6 +755,12 @@ fold_negate_expr (location_t loc, tree t)
>        break;
>      }
>  
> +#ifdef ENABLE_CHECKING
> +  if (negate_expr_p (t))
> +    internal_error ("fold_negate_expr should never return NULL_TREE "
> +                 "if negate_expr_p is true");
> +#endif
> +
>    return NULL_TREE;
>  }
> 
> Fixed by adjusting fold_negate_expr so that it folds non-trapping
> wrapping constants.  The SANITIZE_SI_OVERFLOW check is important
> to not regress -Woverflow warnings (ug).
> 
> negate_expr_p hunk is to match the NEGATE_EXPR case in fold_negate_expr.
>  
> Bootstrapped/regtested on power8-linux, ok for trunk?

Ok.

Thanks,
Richard.

> 2014-11-19  Marek Polacek  <pola...@redhat.com>
> 
>       PR sanitizer/63879
>       * fold-const.c (negate_expr_p) <case NEGATE_EXPR>: Return
>       !TYPE_OVERFLOW_SANITIZED.
>       (fold_negate_expr) <case INTEGER_CST>: Fold when overflow
>       does not trap and when overflow wraps, or when SANITIZE_SI_OVERFLOW
>       is 0.
> 
>       * c-c++-common/ubsan/pr63879-1.c: New test.
>       * c-c++-common/ubsan/pr63879-2.c: New test.
> 
> diff --git gcc/fold-const.c gcc/fold-const.c
> index f6fb8af..719e06e 100644
> --- gcc/fold-const.c
> +++ gcc/fold-const.c
> @@ -408,9 +408,11 @@ negate_expr_p (tree t)
>             && TYPE_OVERFLOW_WRAPS (type));
>  
>      case FIXED_CST:
> -    case NEGATE_EXPR:
>        return true;
>  
> +    case NEGATE_EXPR:
> +      return !TYPE_OVERFLOW_SANITIZED (type);
> +
>      case REAL_CST:
>        /* We want to canonicalize to positive real constants.  Pretend
>           that only negative ones can be easily negated.  */
> @@ -555,7 +557,8 @@ fold_negate_expr (location_t loc, tree t)
>        tem = fold_negate_const (t, type);
>        if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t)
>         || (!TYPE_OVERFLOW_TRAPS (type)
> -           && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0))
> +           && TYPE_OVERFLOW_WRAPS (type))
> +       || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
>       return tem;
>        break;
>  
> diff --git gcc/testsuite/c-c++-common/ubsan/pr63879-1.c 
> gcc/testsuite/c-c++-common/ubsan/pr63879-1.c
> index e69de29..2035849 100644
> --- gcc/testsuite/c-c++-common/ubsan/pr63879-1.c
> +++ gcc/testsuite/c-c++-common/ubsan/pr63879-1.c
> @@ -0,0 +1,23 @@
> +/* PR sanitizer/63879 */
> +/* { dg-do compile } */
> +/* { dg-options "-fsanitize=undefined" } */
> +
> +struct A
> +{
> +  int inode;
> +} * a;
> +int b, c;
> +void
> +fn1 ()
> +{
> +  int d = 0;
> +  while (b)
> +    {
> +      if (a->inode)
> +        d++;
> +      a = 0;
> +    }
> +  c = d - 1;
> +  for (; c >= 0; c--)
> +    ;
> +}
> diff --git gcc/testsuite/c-c++-common/ubsan/pr63879-2.c 
> gcc/testsuite/c-c++-common/ubsan/pr63879-2.c
> index e69de29..34eb8e7 100644
> --- gcc/testsuite/c-c++-common/ubsan/pr63879-2.c
> +++ gcc/testsuite/c-c++-common/ubsan/pr63879-2.c
> @@ -0,0 +1,13 @@
> +/* PR sanitizer/63879 */
> +/* { dg-do compile } */
> +/* { dg-options "-fsanitize=undefined" } */
> +
> +int a;
> +void
> +fn1 ()
> +{
> +  int b = 2;
> +  for (; a;)
> +    while (b >= 0)
> +      b--;
> +}
> 
>       Marek
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendoerffer, HRB 21284
(AG Nuernberg)
Maxfeldstrasse 5, 90409 Nuernberg, Germany

Reply via email to