|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
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 |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 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 ? |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 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. |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
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 |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
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 <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 |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
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. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7925 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. |
|
Back to top |
|
|
|
|
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
|