On Mon, 31 Jul 2017, Jakub Jelinek wrote:

> Hi!
> 
> ipa_polymorphic_call_context offset field is in bits (for whatever reason),
> and the following computations can overflow and invoke UB.
> This patch computes it in offset_int instead and punts if there is overflow.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.  As said in the PR the machinery should probably use byte offsets
throughout (do we support any target where HWI < size of ptr_mode?  That 
is, 128bit pointers?)

Richard.

> 2017-07-31  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR tree-optimization/81603
>       * ipa-polymorphic-call.c
>       (ipa_polymorphic_call_context::ipa_polymorphic_call_context): Perform
>       offset arithmetic in offset_int, bail out if the resulting bit offset
>       doesn't fit into shwi.
> 
> --- gcc/ipa-polymorphic-call.c.jj     2017-06-12 12:41:55.000000000 +0200
> +++ gcc/ipa-polymorphic-call.c        2017-07-28 15:02:43.747354910 +0200
> @@ -921,9 +921,13 @@ ipa_polymorphic_call_context::ipa_polymo
>                and MEM_REF is meaningless, but we can look futher.  */
>             if (TREE_CODE (base) == MEM_REF)
>               {
> +               offset_int o = mem_ref_offset (base) * BITS_PER_UNIT;
> +               o += offset;
> +               o += offset2;
> +               if (!wi::fits_shwi_p (o))
> +                 break;
>                 base_pointer = TREE_OPERAND (base, 0);
> -               offset
> -                 += offset2 + mem_ref_offset (base).to_short_addr () * 
> BITS_PER_UNIT;
> +               offset = o.to_shwi ();
>                 outer_type = NULL;
>               }
>             /* We found base object.  In this case the outer_type
> @@ -961,10 +965,15 @@ ipa_polymorphic_call_context::ipa_polymo
>           break;
>       }
>        else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
> -            && tree_fits_uhwi_p (TREE_OPERAND (base_pointer, 1)))
> +            && TREE_CODE (TREE_OPERAND (base_pointer, 1)) == INTEGER_CST)
>       {
> -       offset += tree_to_shwi (TREE_OPERAND (base_pointer, 1))
> -                 * BITS_PER_UNIT;
> +       offset_int o = offset_int::from (TREE_OPERAND (base_pointer, 1),
> +                                        SIGNED);
> +       o *= BITS_PER_UNIT;
> +       o += offset;
> +       if (!wi::fits_shwi_p (o))
> +         break;
> +       offset = o.to_shwi ();
>         base_pointer = TREE_OPERAND (base_pointer, 0);
>       }
>        else
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to