![forums.silverfrost.com Forum Index](templates/subSilver/images/logo_phpBB.gif) |
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Mon Feb 19, 2018 9:39 pm Post subject: Failure to catch array overrun even with /check specified |
|
|
Here is a short program in which '55' was typed in on Line-7, but '5' was intended.
Code: | PROGRAM subsbug
IMPLICIT NONE
integer, parameter :: ND = 5
REAL :: alf(2), w(ND)
INTEGER :: l, n
!
n=55 ! should have been '5', but error was made
l = 3
w(1:n) = 1.0 ! array overrun here, not caught
alf = [1e-2, 2e-2]
PRINT *,l,n ! prints "1065353216 1065353216"
PRINT *,alf
END PROGRAM subsbug |
When we compile and run this with FTN95 8.10, in 32-bit mode the first line output is as shown in the comment. If we try to catch the bug by recompiling with /check, the bug is not caught.
In 64 bit mode, compiling without /check and running outputs "3 55", but the program hangs. Opening the EXE in SDBG64 shows "Error: Access Violation reading address 0xFFFFFFFFFFFFFFFF".
Last edited by mecej4 on Mon Feb 19, 2018 11:19 pm; edited 1 time in total |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Mon Feb 19, 2018 11:11 pm Post subject: |
|
|
If alf and w are in COMMON (named or blank) the output is 3 and 55.
Is that any help? Presumably it's a memory map issue. what a pity that the details of that aren't easy to get hold of.
Eddie
Last edited by LitusSaxonicum on Mon Feb 19, 2018 11:26 pm; edited 1 time in total |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Mon Feb 19, 2018 11:23 pm Post subject: |
|
|
Your changes may cause the expected values to be printed out, without /check. However, with /check, did placing those variables in COMMON cause the array overrun to be detected?
Changing the source code in that manner generally causes the clobbering to happen to some other area of memory. If we are not watching those areas, the damage may remain hidden for a while, but it will have occurred. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Tue Feb 20, 2018 1:09 am Post subject: |
|
|
With /check, the right results are printed out, but there is still no bounds check. I tried WINAPP as well - still no check on array bounds (v8.1 32-bit).
Is it a regression, or has /CHECK never worked? Did it work in FTN77?
Exceeding array bounds used to cause all sorts of mayhem, including OS crashes. Windows may have its problems, but it is a long time since I crashed a PC with a programming error!
My point was that I'd like to see the memory map. It's a requisite if you are to program defensively, but the details aren't published. Perhaps they should be. The weird thing is that alf is stored after w when they are local, but in a COMMON block, alf is stored before w - and that's interesting, isn't it? Interesting that 64 bit hangs, but 32 bit doesn't. That must mean something about where executable code is stored in memory too.
I always program in a check that I'm not exceeding the upper limit of an array, normally when the user inputs or generates a value, probably because I've been used to small and fixed limits. Plus, I allow plenty of room now that I can. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Tue Feb 20, 2018 1:45 am Post subject: |
|
|
I tried /check /lis /exp, and this is what I found.
For the array assignment, i.e., w(1:n) = 1.0, the compiler generates no checking code. Instead, it finds how many words to store, and generates the corresponding REP STOSD instruction, with count n, regardless of whether /check was specified. Thus, if we want checking, we have to revert to DO loops in which array elements are set to desired values. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7928 Location: Salford, UK
|
Posted: Tue Feb 20, 2018 10:11 am Post subject: |
|
|
Thank you for this. I have made a note that FTN95 /CHECK does not detect this particular programming error. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Tue Feb 20, 2018 10:25 am Post subject: |
|
|
I can confirm this issue also exists in version 7.2.
I believe this kind of array bounds error used to be caught with /CHECK or even with /BOUNDS_CHECK (Version 6?).
But since the compiler started to use REP STOSD this check can't be implemented on every element.
A more serous bug is that if you change the line to the following (in an attempt to defeat the use of REP STOSD) the "initialisation loop" doesn't terminate and the program doesn't complete (at least in 7.2).
I think it is important that a check is done, either by forcing use of a loop when /BOUNDS_CHECK or /CHECK is used or by checking the end points:
Code: |
Consider access to w(a:b:s)
b + 1 - max(s,0) > ubound(w) -> bounds error (upper bound)
a - 1 - min(s,0) < lbound(w) -> bounds error (lower bound)
|
Note how the stride s is handled. Some care is needed with non-unit strides because the following code is perfectly legal:
Code: |
real w(5)
w(1:6:2) = 1.0
|
Such code is quite common and must pass the bounds checking process. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7928 Location: Salford, UK
|
Posted: Tue Feb 20, 2018 11:08 am Post subject: |
|
|
David
Thank you for the feedback. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Tue Feb 20, 2018 2:11 pm Post subject: |
|
|
David, thanks for the interesting analysis. From the assembly listing for your initialization statement
w(n:1:-1) = 1.0
a code loop is generated(no STOSD), but the problem persists.
I can see that both W() and N are on the stack, with W assigned a lower address than N. When the index of W() becomes large enough, W(i) may overlap N. At that point, W(i) has overwritten N and, depending on the value that was overwritten, the program may go into a never-ending loop or abort with an access violation.
It appears that /check does not do a thorough job in this instance. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7928 Location: Salford, UK
|
Posted: Wed May 16, 2018 10:18 am Post subject: |
|
|
Given w(5) and n = 55...
1) A bounds check has now been added for w(1:n) = 1.0 for both /check and /undef and for both 32 bits and 64 bits.
2) w(1:6:2) = 1.0 still gives a compile time error with /check (this is a false error report which I think we will have to tolerate).
3) w(n:1:-1) = 1.0 is still not trapped and loops at runtime. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|