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 

Failure to catch array overrun even with /check specified

 
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: 909

PostPosted: Mon Feb 19, 2018 9:39 pm    Post subject: Failure to catch array overrun even with /check specified Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 1790
Location: Yateley, Hants, UK

PostPosted: Mon Feb 19, 2018 11:11 pm    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 909

PostPosted: Mon Feb 19, 2018 11:23 pm    Post subject: Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 1790
Location: Yateley, Hants, UK

PostPosted: Tue Feb 20, 2018 1:09 am    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 909

PostPosted: Tue Feb 20, 2018 1:45 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Tue Feb 20, 2018 10:11 am    Post subject: Reply with quote

Thank you for this. I have made a note that FTN95 /CHECK does not detect this particular programming error.
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 553
Location: UK

PostPosted: Tue Feb 20, 2018 10:25 am    Post subject: Reply with quote

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

Code:

w(n:1:-1) = 1.0


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
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Tue Feb 20, 2018 11:08 am    Post subject: Reply with quote

David

Thank you for the feedback.
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 909

PostPosted: Tue Feb 20, 2018 2:11 pm    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Wed May 16, 2018 10:18 am    Post subject: Reply with quote

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
View user's profile Send private message
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