forums.silverfrost.com
Welcome to the Silverfrost forums

Author Message
mecej4

Joined: 31 Oct 2006
Posts: 1743

Posted: Tue Nov 08, 2022 8:25 am    Post subject: Spurious integer overflow: Short new reproducer

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
JohnCampbell

Joined: 16 Feb 2006
Posts: 2434
Location: Sydney

 Posted: Tue Nov 08, 2022 11:07 am    Post subject: 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 ?
PaulLaidler

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

 Posted: Tue Nov 08, 2022 11:33 am    Post subject: 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.
mecej4

Joined: 31 Oct 2006
Posts: 1743

Posted: Tue Nov 08, 2022 1:55 pm    Post subject: Re:

 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
mecej4

Joined: 31 Oct 2006
Posts: 1743

Posted: Tue Nov 08, 2022 2:34 pm    Post subject: Re:

 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 [/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  [
FTN95 v8.92.0]     NO ERRORS  [ FTN95 v8.92.0]     NO ERRORS  [ FTN95 v8.92.0] WARNING T:\ODE\LLNLVODE\V90\CULL\sovfl.F 63:  The argument FUNC has not been used     NO ERRORS, 1 WARNING  [ FTN95 v8.92.0]     NO ERRORS  [ FTN95 v8.92.0]     NO ERRORS  [ FTN95 v8.92.0]
mecej4

Joined: 31 Oct 2006
Posts: 1743

Posted: Tue Nov 08, 2022 3:23 pm    Post subject: Re:

 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.
PaulLaidler

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

 Posted: Tue Nov 08, 2022 5:08 pm    Post subject: 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.
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 All times are GMT + 1 Hour Page 1 of 1