[PATCH] Perform ubsan instrumentation for x >= 0 ? x : -x

Richard Biener rguenther@suse.de
Tue Mar 25 09:13:00 GMT 2014


On Tue, 25 Mar 2014, Jakub Jelinek wrote:

> Hi!
> 
> While Marek has been debugging while some perl test fails when perl is built
> with GCC 4.9, we've discovered that it is because of undefined behavior in
> it:
> ...
>   && (((UV)1 << NV_PRESERVES_UV_BITS) >
>       (UV)(SvIVX(sv) > 0 ? SvIVX(sv) : -SvIVX(sv)))
> where SvIVX(sv) can be LONG_MIN, at which point there is undefined behavior
> on the negation, but -fsanitize=undefined did detect only other issues in
> the same source file and not this one, because fold-const.c folded it into
> ABS_EXPR early.
> 
> This patch disables such folding, because all the A op 0 ? A : -A
> operations this if is trying to optimize will need instrumentation with
> -fsanitize=signed-integer-overflow.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Can't one form a valid constant expression using this?  Also isn't
ABS_EXPR undefined for LONG_MIN as well?  So why is ubsan not
instrumenting that instead?

Thanks,
Richard.
 
> 2014-03-25  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR sanitizer/60636
> 	* fold-const.c (fold_cond_expr_with_comparison): Don't
> 	fold A op 0 ? A : -A if -fsanitize=undefined.
> 
> 	* c-c++-common/ubsan/pr60636.c: New test.
> 
> --- gcc/fold-const.c.jj	2014-01-03 11:40:35.000000000 +0100
> +++ gcc/fold-const.c	2014-03-24 17:59:45.395445617 +0100
> @@ -4718,7 +4718,13 @@ fold_cond_expr_with_comparison (location
>  	      && operand_equal_p (TREE_OPERAND (arg1, 0),
>  				  TREE_OPERAND (arg2, 1), 0)
>  	      && operand_equal_p (TREE_OPERAND (arg1, 1),
> -				  TREE_OPERAND (arg2, 0), 0))))
> +				  TREE_OPERAND (arg2, 0), 0)))
> +      /* Don't fold this if sanitizing undefined behavior,
> +	 -A or Y-X might overflow and after folding this we wouldn't
> +	 be able to detect that.  */
> +      && ((flag_sanitize & SANITIZE_SI_OVERFLOW) == 0
> +	  || !INTEGRAL_TYPE_P (TREE_TYPE (arg01))
> +	  || TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg01))))
>      switch (comp_code)
>        {
>        case EQ_EXPR:
> --- gcc/testsuite/c-c++-common/ubsan/pr60636.c.jj	2014-03-24 18:04:33.875925324 +0100
> +++ gcc/testsuite/c-c++-common/ubsan/pr60636.c	2014-03-24 18:09:18.696419079 +0100
> @@ -0,0 +1,15 @@
> +/* PR sanitizer/60636 */
> +/* { dg-do run } */
> +/* { dg-options "-fsanitize=undefined" } */
> +
> +volatile long long int a;
> +
> +int
> +main ()
> +{
> +  long long int u = -__LONG_LONG_MAX__ - 1;
> +  a = u > 0 ? u : -u;
> +  return 0;
> +}
> +
> +/* { dg-output "negation of -9223372036854775808 cannot be represented in type 'long long int'" } */
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer



More information about the Gcc-patches mailing list