forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Spurious integer overflow: Short new reproducer

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Tue Nov 08, 2022 8:25 am    Post subject: Spurious integer overflow: Short new reproducer Reply with quote

Paul,

I have succeeded in constructing a short reproducer for the false integer overflow bug that I reported recently ( http://forums.silverfrost.com/viewtopic.php?p=33464 ). The new reproducer is straight Fortran 77, with less than 100 lines. To see the bug, please compile with /check, link and run. The program aborts with integer overflow on line 71.

Thanks.

Code:
      program main

      implicit none
      integer  lrw, neq
      real     y(2), rwork(50)
      EXTERNAL fsub
!
      lrw  = 50
      neq  = 2
      y(1) = 2.0
      y(2) = 0.0
      call dvode (fsub, neq, y, rwork, lrw)
      stop
!
      end !program main

      subroutine dvode(func, neq, y, rwork, lrw)

      implicit none
      integer   neq, lrw, i, lf0
      real      y(neq), rwork(lrw)
      integer   n, lewt, lyh

      EXTERNAL func

      n = neq
      lyh = 21
      lewt = lyh + 13*n
      lf0 = lyh + n
      call func (y, rwork(lf0))
      do i = 1,n
         rwork(lyh+i-1) = y(i)
      end do
      do i = 1, n
         rwork(i+lewt-1) = 1.0e6
         rwork(lf0+i-1) = 3.0e-6*rwork(lf0+i-1)
      end do
      call dvstep (y, rwork(lyh), n, func)   ! section of 1-D work array passed for 2-D array in callee
      return

      end !subroutine dvode

      subroutine dvstep(y, yh, ldyh, func)

      implicit none
      integer   ldyh
      real      y(2), yh(ldyh,2)

      integer i

      EXTERNAL func

      do i = 1, ldyh
          yh(i,1) = yh(i,1) + yh(i,2)
      end do
      call dvnlsd (y, yh, ldyh, func)
      return

      end !subroutine dvstep
!
!the subroutine arg func is not used in this bug reproducer, but needs to be present
!to preserve the overflow bug
!
      subroutine dvnlsd(y, yh, ldyh, func)

!      implicit none  ==>> activating this line makes bug disappear
      integer  ldyh
      real     y(ldyh), yh(ldyh,*) !replacing '*' by 2 makes bug disappear

      EXTERNAL func
      call dcopy (2, yh(1, 1), y) ! Integer overflow here with /check
      stop 'Normal completion'

      end !subroutine dvnlsd

      subroutine dcopy(n, dx, dy)

      implicit none
      integer  n, i
      real     dx(n), dy(n)

      do i = 1, n
         dy(i) = dx(i)
      end do

      return
      end !subroutine dcopy

      subroutine fsub(y, ydot)

      implicit none
      real  y(2), ydot(2)

      ydot(1) = y(2)
      ydot(2) = 3.0*(1.0 - y(1)*y(1))*y(2) - y(1)

      return
      end !subroutine fsub


Last edited by mecej4 on Tue Nov 08, 2022 1:27 pm; edited 1 time in total
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Tue Nov 08, 2022 11:07 am    Post subject: Reply with quote

mecej4,

In subroutine dvnlsd(y, yh, ldyh, func)
You define EXTERNAL func, but the function is never used/referenced.
Have you made the reproduced too brief ?

Also, fsub is a subroutine, not a function. I have only used EXTERNAL for a function in the very limited cases where I have used EXTERNAL to define a dummy argument.

Is this an extension to the use of EXTERNAL for a dummy subroutine name ?
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Tue Nov 08, 2022 11:33 am    Post subject: Reply with quote

mecej4

Thank you for the new reduced code.

In the main program fsub is passed as an argument in the call to dvode.
In dvode fsub (now func) is passed as an argument in the call to dvstep.
In dvstep func is passed as an argument in the call to dvnlsd.
dvnlsd has a "star-sized" assumed size array yh.

Part of /CHECK mode works by passing extra arguments to provide array bounds checking but the compiler should suppress this check when calling a subroutine that is passed an argument. It looks like this program is just too complex for the compiler and only part of the checking code has been planted.

This issue is on the list for further investigation but in the meantime /inhibit_check 5 (or 6) must be used for this program when using /check.
Back to top
View user's profile Send private message AIM Address
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Tue Nov 08, 2022 1:55 pm    Post subject: Re: Reply with quote

JohnCampbell wrote:
..., fsub is a subroutine, not a function. I have only used EXTERNAL for a function in the very limited cases where I have used EXTERNAL to define a dummy argument.

Is this an extension to the use of EXTERNAL for a dummy subroutine name ?


John, thanks for your interest. We may think of EXTERNAL as a type similar to CHARACTER or LOGICAL. The only "arithmetic" that one can do with this type is to CALL it, JUMP to it (not in Fortran, but in assembly) or pass it along. EXTERNAL serves to prevent one from applying implicit typing rules to such a variable. There was no other means of describing it in early versions of Fortran, prior to the introduction of INTERFACE declarations. You may find the following quotation (page 7.6, PDF page 84) from the DEC-10 Fortran manual http://www.bitsavers.org/www.computer.museum.uq.edu.au/pdf/DEC-10-AFDO-D%20decsystem10%20FORTRAN%20IV%20Programmer%27s%20Reference%20Manual.pdf quite clear:

Quote:
7.7 EXTERNAL STATEMENT

FUNCTION and SUBROUTINE subprogram names may be used as the actual arguments of subprograms. Such subprogram names must be distinguished from ordinary variables by their appearance in an EXTERNAL statement.
The EXTERNAL statement has the form:

EXTERNAL identifier , identifier, .•• , identifier

This statement declares the listed identifiers to be subprogram names. Any subprogram name given as an argument to another subprogram must have previously appeared in an external declaration in the calling program (i.e., as
an identifier in an EXTERNAL or CALL statement or as a function name in an expression).


Note that this description does not attempt to make any distinction between subroutines versus functions. In C, the matter is handled by providing the void type declaration, the comma operator, etc.

For the nonsensical context in my bug reproducer, EXTERNAL is syntactic sugar. Its presence may also serve as a "keep away" warning to a future programmer who may be tempted to misuse such a non-data-type variable in arithmetic expressions.


Last edited by mecej4 on Tue Nov 08, 2022 3:05 pm; edited 1 time in total
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Tue Nov 08, 2022 2:34 pm    Post subject: Re: Reply with quote

PaulLaidler wrote:
mecej4

...
This issue is on the list for further investigation but in the meantime /inhibit_check 5 (or 6) must be used for this program when using /check.


Thanks, Paul. Specifying /inhibit_check 5 seems to have no effect with this code -- this is probably as it should be, since there are no argument type/size mismatches in the test program. However, /inhibit_check 6 did work.

The compiler is rather rigid about the placement of options in the command line.

It rejects the following version:
Code:
T:\ODE\LLNLVODE\V90\CULL>ftn95 /check /inhibit_check 5 sovfl.f
[FTN95/Win32 Ver. 8.92.0 Copyright (c) Silverfrost Ltd 1993-2022]
*** No source file specified
*** Usage: ftn95 <file-name> [/option [/option ...]]
*** Or:    ftn95 /? for more information on command-line options.


but accepts

Code:
T:\ODE\LLNLVODE\V90\CULL>ftn95 sovfl.f /check /inhibit_check 5
[FTN95/Win32 Ver. 8.92.0 Copyright (c) Silverfrost Ltd 1993-2022]
    NO ERRORS  [<MAIN> FTN95 v8.92.0]
    NO ERRORS  [<DVODE> FTN95 v8.92.0]
    NO ERRORS  [<DVSTEP> FTN95 v8.92.0]
WARNING T:\ODE\LLNLVODE\V90\CULL\sovfl.F 63:  The argument FUNC has not been used
    NO ERRORS, 1 WARNING  [<DVNLSD> FTN95 v8.92.0]
    NO ERRORS  [<DCOPY> FTN95 v8.92.0]
    NO ERRORS  [<FSUB> FTN95 v8.92.0]
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Tue Nov 08, 2022 3:23 pm    Post subject: Re: Reply with quote

PaulLaidler wrote:
mecej4

In dvstep func is passed as an argument in the call to dvnlsd. dvnlsd has a "star-sized" assumed size array yh.

Part of /CHECK mode works by passing extra arguments to provide array bounds checking but the compiler should suppress this check when calling a subroutine that is passed an argument.


Putting these comments from you together with what I saw in the assembly window of SDBG in the location where the overflow occurs gives me an idea for a potential solution.

Usually, when a Fortran program contains '*' in the declarations of array dummy arguments, checking whether subscripts in that dimension are within bounds is not possible with the limited information available. The '*' is equivalent to the programmer telling the compiler, "Don't bother checking the bounds for that specific variable". When the compiler-inserted checking code loads the array bound into a register, for such a "star-sized" argument it will probably load 0x80808080 in the 32-bit case and 0x8080808080808080 in the 64-bit case. It could add a couple of instructions in the subscript checking code to test for this "undefined" signifier 0x80808080, and suspend the subscript range checking for that particular argument when a match occurs. Once this value is detected, it is inevitable that multiplying by 4 or 8 (byte sizes for scalar integer/real, double real) will cause integer overflow.
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Tue Nov 08, 2022 5:08 pm    Post subject: Reply with quote

mecej4

In the latest version of FTN95 (8.92), inhibiting 5 also inhibits 6 and vice-versa. This might change in the future.

FTN95 /check will check the bounds for star-sized arrays but the cleverness involved in do this could be the root of the current failure.

p.s. It might be the latest version on my machine not v8.92.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group