This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix for fold_negate_expr (PR sanitizer/63879)
- From: Richard Biener <rguenther at suse dot de>
- To: Marek Polacek <polacek at redhat dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 19 Nov 2014 12:46:22 +0100 (CET)
- Subject: Re: [PATCH] Fix for fold_negate_expr (PR sanitizer/63879)
- Authentication-results: sourceware.org; auth=none
- References: <20141119110746 dot GA29446 at redhat dot com>
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 <polacek@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 <rguenther@suse.de>
SUSE LINUX GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendoerffer, HRB 21284
(AG Nuernberg)
Maxfeldstrasse 5, 90409 Nuernberg, Germany