https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77941

--- Comment #10 from Steve Kargl <sgk at troutmask dot apl.washington.edu> ---
On Thu, Mar 22, 2018 at 02:27:25PM +0000, jb at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77941
> 
> --- Comment #8 from Janne Blomqvist <jb at gcc dot gnu.org> ---
> (In reply to Steve Kargl from comment #7)
> > On Thu, Mar 22, 2018 at 07:53:14AM +0000, jb at gcc dot gnu.org wrote:
> > >
> > > It works on x86_64-pc-linux-gnu (including running it), but the ICE 
> > > remains on
> > > i686-pc-linux-gnu.
> > > 
> > 
> > Janne, thanks for checking.  2_8**32+1 is 4GB+1byte of memory.
> > Without PAE, i686 is limited to less than 4GB once an OS grabs a
> > small portion of wired memory.  Do we care if an ICE occurs?
> > I suppose one could always check that a length type parameter
> > less than some max integer based on 32-bit vs 64-bit system, 
> > but that would pessimize all uses of strings as this would 
> > need to be a runtime check.
> 
> If one looks at the -fdump-tree-original dumps, for both i686 and x86-64 the
> function f() looks Ok. However, the program p differs significantly. For 
> x86-64
> the working program p is:
> 

Dumps compressed down to needed lines.

x86_64

>   static void f (character(kind=1)[1:] &, integer(kind=8), integer(kind=8));
> 
>       character(kind=1)[1:4294967297] * pstr.1;
>       void * restrict D.3781;
> 
>       D.3781 = (void * restrict) __builtin_malloc (4294967297);

i686

>   static void f (character(kind=1)[1:] &, integer(kind=4), integer(kind=8));
> 
>       character(kind=1) str.1[1];
> 
>       f ((character(kind=1)[1:1] *) &str.1, 1(OVF), 4294967297);
>       _gfortran_transfer_character_write (&dt_parm.0, (character(kind=1)[1:1]
> *) &str.1, 1(OVF));

The dumps are a little misleading in that f(n) is inlined.
Here, the middle/backend can see n = 2_8**32+1, so it can 
generate the OVF.

If f(n) is in a file by itself the dump looks much different.
(where I've wrapped long lines and this is on x86_64 and
comments in-lined.).

f (character(kind=1)[1:..__result] & __result, integer(kind=8)
   .__result, integer(kind=8) n)
{
  integer(kind=8) ..__result;
  bitsizetype D.3766;
  sizetype D.3767;

  ..__result = MAX_EXPR <n, 0>;

So, gfortran (or middle/backend) protect against a negative
number on i686 .__result is int32.  The above MAXEXPR may cause
2-complement wrap around.  What I want to avoid is

if (n >= intmax_t)
  {
     runtime error here.
  }

for all routines that take a string.


  D.3766 = (bitsizetype)(sizetype)NON_LVALUE_EXPR<..__result> * 8;
  D.3767 = (sizetype) NON_LVALUE_EXPR <..__result>;
  {
    integer(kind=8) D.3764;
    integer(kind=8) D.3765;

    D.3764 = ..__result;
    D.3765 = NON_LVALUE_EXPR <D.3764> + -1;
    if (D.3764 > 0)
      {
        if (NON_LVALUE_EXPR <D.3764> > 1)
          {
            __builtin_memmove ((void *) __result,
                                (void *) &"a"[1]{lb: 1 sz: 1}, 1);
            __builtin_memset ((void *) __result + 1, 32,i
                              (unsigned long) D.3765);
          }
        else
          {
            __builtin_memmove ((void *) __result,
                               (void *) &"a"[1]{lb: 1 sz: 1},
                               (unsigned long) NON_LVALUE_EXPR <D.3764>);
          }
      }
  }
}

Reply via email to