1820619 Members
1860 Online
109626 Solutions
New Discussion юеВ

Re: Overflow

 
SOLVED
Go to solution
Jan van den Ende
Honored Contributor

Overflow

Getting philosofical...

The last few weeks several times the issue of overflow on (especially ported) software has come up several times.
The issue kept nagging, and this afternoon a memory from way back when popped up.

In a former life I did (mostly Filetab and some) Cobol programming on ICL 1900-series "mainframes".

The specific issue that flashed back from the past was a "Special Steering Command" in ICL's Cobol: "WITH BOUNDS CHECKED".
It caused the compiler to generate extra code, which on any data transfer statement checked for Numeric values NOT overflowing/underflowing the defined domains (specifiable, default the full range of the PIC);
and for strings for not TRYING to move larger-than-intended.
Originally this option's main intention was to use it during program development & testing; and when the program went to production the option was removed for performance reasons.

Point is: any data over- or underflowing transfer would halt the program, and generate output that held sufficient info to analyse the issue.

From a VMS perspective such instructions are much better visualised as compiler qualifiers, but the intent should be clear.


Now I am gonna profile myself as a C illiterate, but:

WOULD IT BE TOTALLY INCONCEIVABLE to have this built into the C (C++, others?) compiler?

I imagine that the bulk of VMS sites would gladly accept the performance drawback to get the resulting protection, and the immediate warning upon attempted assault, when using ported software.


Any comments as to desirability, feasability, whatever other issue???


(For my Belgian friends: I had 3 Duvels before writing this, could that be what made me philosofical, or...?)

Cheers.

Join me in my next Duvel.

Jan
Don't rust yours pelled jacker to fine doll missed aches.
35 REPLIES 35
Ian Miller.
Honored Contributor

Re: Overflow

Is that three Duvel Tripels ! (10% by vol for those not following every detail).

Parhaps you could post a message here
http://h71000.www7.hp.com/commercial/c/c_feedback.html

There is the /IEEE_MODE qualifier
http://h71000.www7.hp.com/commercial/c/docs/5492p004.html#index_x_113
/IEEE_MODE=INEXACT may be what you want.
____________________
Purely Personal Opinion
Ian Miller.
Honored Contributor

Re: Overflow

I've read a pile of stuff of on floating point on itanium and don't remember what checks are available.

Having the option for extra checking would be a good thing.
____________________
Purely Personal Opinion
Jan van den Ende
Honored Contributor

Re: Overflow

Ian,

Well, Duvel is not fully 10%. (8.5, and by now I finished the 4th as well)
And is is NOT Tripel (although, if you want to compare it, probably triple comes closest).
The name "Duvel" is dialectic for "Devil", and the story is that it points back to a remark by one of the original brewers: the beer behaved so unpredictable in pooring, drinking, and storing, (and morning-after)that it was "develish". The name stuck, and became the brand.


To (try to) become serious: if this thread will (hopefully) generate support for the idea, I think I will have to enter the formal request.

Your second pointer: this is about what I had expected to find, not too much unlike what I know from languages I know somewhat better.
The available checking is on NUMERIC values.
What made me start this discussion was the availability OVER TWENTY YEARS AGO, of an overflow test FOR STRINGS!

Writing all this down, I also started wondering how much of this is already covered by Hoff's stack-execution-protection in IA64 (which MIGHT even be backported to Alpha).

Maybe someone much deeper into compilers and/or internal workings can shine a light on this?

(and now my wife really is wanting me to quit this, so GOODNIGHT)

Cheers.

Have one on me.

Jan
Don't rust yours pelled jacker to fine doll missed aches.
John Gillings
Honored Contributor

Re: Overflow

Jan,

Compilers have come a long way since the days of mainframes that did little or no checks on calculations. All VAX and Alpha compilers have had range, bounds, overflow and underflow checks, either by default or as an option. One of the "new" features of the VAX architecture back 25 years ago was useable under and over flow checking in hardware for all data types. VAX programmers have always been agast when they learn that some systems did NOT crash a program for a divide by zero error or similar arithmetic fault.

Ian's point is that IEEE floating point arithmetic has even more options for handing over and underflow conditions than VAX had. If C and C++ there is no packed decimal format, see the IEEE related qualifiers to select the most appropriate for your needs.

For COBOL packed decimal arithmetic, these days it's mostly implemented by converting to 64 bit INTEGER for the calculations and converting back to store. That's because 64 bit arithmetic has sufficient precision. COBOL also implements /CHECK=DECIMAL which does bounds checking, as well as "sanity" checking.

Pascal has /CHECK=OVERFLOW.
Fortran has /CHECK=(OVERFLOW,FP_EXCEPTIONS,UNDERFLOW)

Please provide an example of a program with the kind of error that you're thinking of where you don't get useful errors by default, or cannot request errors with an existing compiler qualifier.
A crucible of informative mistakes
Jan van den Ende
Honored Contributor

Re: Overflow

John,

what I was specifically thinking of was the fenomenon in ported C-language programs where buffer overflow capability generates security holes.

And although in my old ICL Cobol days THAT was not an issue, it was possible for code WITHOUT the BOUNDS CHECKED to mis-manipulate strings to fill address space beyond the areaintended for the string.
The simple demo program added 1 character to a growing string in a loop, that for the demo purpose ran much longer than the receiving string could handle.
WITH the bounds checked, the programm AB-ENDED, indicating why and when it broke.
WITHOUT the bounds checked, the programm went trough the loop much too often, and corrupted the datafile that it was updating.
With a minor input change it ran still longer, and then crashed because some instructions had been changed into something invalid,and were attempted to be executed. In that case the post-mortum was also of little value.

So: would it be somehow possible to have the option to have the compiler generate code that would detect the infamous string (buffer-) overflows, and tell the user WHY the code is not functioning.

-- and I really have not the faintest idea how this should be implemented. Maybe by simply implementing the null-terminated string as a descriptor-described entity that happens to have a null as last byte.
(this may be utter nonsense though, just my shot in the dark).

Cheers.

Have one on me.

Jan
Don't rust yours pelled jacker to fine doll missed aches.
John Gillings
Honored Contributor

Re: Overflow

Jan,

Sorry, I misunderstood which type of overflow you were talking about.

All VAX and Alpha compilers have /CHECK=BOUNDS which will generate code to check the array bounds of all stores. However, this unfortunately won't always help C and C++.

The issue mostly has to do with the way strings are handled - length being defined by null termination. In most other languages, there is a mechanism to pass decalred string lengths to subroutines (OpenVMS uses descriptors), but many C and C++ routines are passed only the address of the string. The code assumes (hopes?) that the allocation is "large enough", but has no way of knowing.

C programmers could write code that uses a more complex object to represent strings -one that includes bounds information. There are some newer RTL routines which help. For example, instead of "strcpy" use "strncpy" which includes a maximum length. It's all a matter of defensive programming.

In theory, one could put guard areas around selected objects. For large objects allocate a page on each side and protect it against access (OpenVMS memory protection granularity is one page). This would be expensive, especially for many objects, and really doesn't completely guarantee to trap all overflows (consider, what if the offset from the start of the string is greater than a page? You could leapfrog the string and the guard page and corrupt something else, undetected).

Less expensive in memory, but more expensive in processing is to put smaller guard areas with a "poison pattern". After any write access, check the guard areas to see if the pattern has changed. Again, costly without a guarantee.

Stronger typed languages, like Ada and Pascal will give you much of this protection automatically.

My fear is we could implement more complex and costly "protection" mechanisms in compilers, and the nett result would be programmers just get sloppier and less disciplined! They expect the compiler to catch their mistakes, so don't bother to engineer code properly.

That's the ultimate defense against this kind of error - good sound engineering practices!
A crucible of informative mistakes
Wim Van den Wyngaert
Honored Contributor

Re: Overflow

Overflow is a serious problem, for Duvels.
When you are to fast, overflow may be a problem. So slow putting into the glas is advised.

For non-Duvel users (called novices) : http://www.duvel.be/pages/Main.aspx?culture=en&pageid=merken/duvel/introductie

I used to be a Cobol expert too : 1 advise : compile your sources on al platforms (Unix, HP3000, VMS) and all compilers will find some bugs. At run time they all check different things. HP3000 had a stack that resulted in run time errors and all compilers had options that checked things in a different way.

When moving a big applic from HP3000 to VMS a lot of errors where found !

Wim
Wim
Antoniov.
Honored Contributor

Re: Overflow

Jan,
your question has thousand answer ...
About outbound trouble, I remember when teached me about trap in if/loop statement.
For example this code may fail:
01 I pic 9(3) comp.
01 A pic X occurs 10 times.
move 1 to I.
perform until (A(I) = "T" or I > 10)
...
add 1 to I;
end-perform.

This code works fine:
01 I pic 9(3) comp.
01 A pic X occurs 10 times.
move 1 to I.
perform until (I > 10 or A(I) = "T")
...
add 1 to I;
end-perform.

In first case, A(I) when I = 11 fail if program compiled with outbound check, works if compiled without check :-O

Antonio Vigliotti
Antonio Maria Vigliotti
Ian Miller.
Honored Contributor

Re: Overflow

If the CRTL allocated memory from a zone it created (which I think it does) then that zone could have appropriate options so it could be checked with LIB$VERIFY_VM_ZONE. This could catch overflows of buffers allocated with malloc. You may be able to add your own checking code if the zone used by the CRTL has a obvious name. Use LIB$FIND_VM_ZONE to look through the zones to fine the right one then use LIB$VERIFY_VM_ZONE to check it whenever you like.
I suppose the CRTL could do this (enabled by yet another feature logical).

This would not address overflows of buffers on the stack or in static memory. I suppose the compiler could add extra code for those cases.

C is not a language that supports this sort of checking easily.
____________________
Purely Personal Opinion
Wim Van den Wyngaert
Honored Contributor

Re: Overflow

Antonio,

Your working example only works if there is something declared after the A table.

All,

Checking programs goes further than bounds and overflows. I once wrote a program to check more :
1) are IFs alligned correctly : especially in cobol due to the "." which is a superendif.
2) are AND and OR not mixed in dubious statements : if var1 = "a" or "b" and var2 = "c" is dubious. Place () to make sure that it is correct.
3) are the GO TO's correctly used : allowed are those pointing to the exit paragraph of the current paragraph (idem section). All others must be forbidden.
4) is the total length of a statement longer than x lines (x about 100 or lower). Must be forbidden to keep programs readable.
5) are variables declared but unsed : old garbage.
6) unsed paragraphs : indicates that the PERFORM was removed or that it is a comment (in which case an * must be used)
...

And even more : scan all sources and report subprograms that are not called (anymore).

Wim (Dry, no Duvel consumed yet)
Wim
Bojan Nemec
Honored Contributor

Re: Overflow

It will be great, if such protection could be implemented. And no only for testing purposes. But I am affraid that this is not a simple task without a great performance drawback, because of the C nature. You must look to C as a near assembler language where you can do (almost) everything. Bad things can be written in almost all languages but in C is much "easier". Take the next example in COBOL:

1 a pic x(10).
1 b pic x(10).
...
call "sub" using a.


program-id.sub.
...
linkage section.
1 a pic x(20).
procedure division using a.
...
move all "a" to a

You can compile this 2 examples with /CHECK=BOUNDS but there will be no error!
Ok, this is an abuse in COBOL, but the C str* functions work in a very similar way, that means that (as John mentioned) this functions must not be used.

In VMS there are some things that can prevent some stack buffer overflow attacks.
The stack is "growing" from the end of the P1 space down to the P0 space. An attacker must be able to write in an address which is greather than the buffer (this is not true when the buffer is passed to the program as an parameter).
Stacks are ordered by mode. The topmost is user then supervisor,executive and kernel and a guard region. So if the whole stack is overflowed there is an access violation.
The only way is to mess pointers or indexes which are behind the buffer.
Now some ideas which came to me when writing this. Put some guard regions on the stack. These regions will be created automaticly when calling a function. Example of stack:

...
function call frame
function data
--read only page
function call frame
function data
--read only page
function call frame

and so on.
With this the function cant mess with more than one frame without an access violation. Another thing is messing with addresses and indexes. When defining filds, it will be oportune that they are rapresented in memory in the same order, so you can put indexes and adresses in front of buffers. But this will be a programer choice and try to persuade a C programer to not write:
char buf[512]; char * p = buf;

By the way VMS CC has the /CHECK=BOUNDS qualifier, but it has many (not check if;-) and probably works as in COBOL - no checks in functions.

Bojan
Jan van den Ende
Honored Contributor

Re: Overflow

Well,

my first (minor) target is reached: it seems I did succeed in starting the discussion going.


And, indeed, I was NOT intending on a discussion about NUMERIC overflow, but solely about STRING OF.

We all recognise this as the stuff that vulnerability holes are made of, and the deeper source usually is C's standard null-terminated string.

(well, not really the string and its normal uses, but the ease with which it can be mis-used.


John:
Yes! What I was hoping to push to the frontlight was "defensive programming, as a good engeneering practise", and, HOPEFULLY, to think of a way to seduce the compiler engeneers to develop a "construct", such that (especially PORTED) software would _BY DEFAULT_ be protected against (at least the most common) abuses. And if that would be at the price of lost performance: I think every-one with a VMS-mindset would be happy to pay the price.

_IF_ you NEED the extra performance, THAN you can amend the compile command (and anything else in the MAKE), but THAT would be a specific DECISION, and thereby forcing you to at least THINK about WHICH amends you are making, and WHY, and therefor, the CONSEQUENCES. A good VMS programmer probably then also would amend some parts of the code to reach desired performance without the holes.

The BASIC principle of my point is that at the moment any "quick" porting of software ALSO ports the holes, while a DEFAULT port should BY DEFAULT include "normal" VMS stability and security.

Ian, Bojan:
I was hoping for this kind of ideas to put to the compiler builders!

Antonio:
such was my experience 20-odd years ago that triggered this stream!

Wim:
Maybe such kind of tests could also be done by the compiler, but since that would be over and above the language specs, even IF that can be implemented, it would have to be an "extra", like, say, a compiler switch /GOOD_PRACTISE_ENFORCED

About your Duvel site:
perhaps you, or Kris, or myself, should have given this pointer long ago allready!
Beer-lovers of this forum: Follow that link! Enjoy it! Get thirsty! And get yourself a Duvel..!

Cheers.

Have one on me (a Duvel this time!).

jpe
Don't rust yours pelled jacker to fine doll missed aches.
John Gillings
Honored Contributor

Re: Overflow

Jan,

Biased opinion...

>HOPEFULLY, to think of a way to seduce the compiler engeneers to develop a "construct", such that (especially PORTED) software would _BY DEFAULT_ be protected against (at least the most common) abuses.

Already done! It's very simple, your compilation statement will be:

$ PASCAL

or

$ ADA

:-)

The trick is to have the language defined so the compiler is aware of ALL source code.

Most programming errors occur across routine interfaces. Most of those are because the two sides of the interface have different views of reality. Most languages make it difficult to ensure consistency. Pascal and Ada make it difficult to code INconsistencies.

So, Bojan's example where the caller declared an array to be 10 elements but the called routine declared it to be 20, simply doesn't happen in Pascal or Ada because the compiler uses the same definition for the same object. Thus, when passing a string or array to a subroutine the subroutine KNOWS the declared dimensions and can easily check for overflowing the bounds.

Back in my teaching days, I recall a student once complaining about being taught Pascal instead of C. "It's like programming in a straight jacket - the compiler treats me like an idiot". My response was that I prefer Pascal because compilers had proven time and again that I *AM* an idiot, and need to be protected against myself!

Good solid design can also help eliminate errors like overflows. The conceptual objects need to be well designed with a minimum of code that "knows" the implementation of an object. For example, have a "buffer" object, but hide the internal detail, except to a minimum of operators. If you want to manipulate the buffer you MUST use the "official" routines. This is sometimes called "object oriented", "modular design" or "information hiding". It's applicable to ALL code, in all languages, not just the "OO" languages.
A crucible of informative mistakes
Martin P.J. Zinser
Honored Contributor

Re: Overflow

Hi Jan,

while certainly not a magic bullet, some additional checking on C sources can be
achieved using DCC (see http://zinser.no-ip.info/vms/sw/dcc.htmlx for some more information, and yes I know I need to update the port).

But since this is a philosopical discussion anyhow, I shall step on the soapbox too ;-)

When has a piece of software been ported? If you get it to compile somehow and it does not crash if you do a mcr sys$disk:[]foo --help?
If you can do foo/opt=(val,...), have an entry in VMS help and pass all strings by descriptors?

Actually in <> opinion to one most important thing is to get whatever changes you need to make the program work properly on VMS back into the main source tree, so that once the next version is released you can build on what already has been done and do not start to re-apply the same changes again and again. How do you achieve this? Pointing out some places where you can improve general code quality (including concrete patches) usually is a good door opener, and the hp C compiler is good a catching many of these. Telling somebody to change pretty much any instance of string handling will most probably alienate the developers (If you feel suicidal try to talk to your internal developers about this ;-) . So whatever bounds checking would be implemented it really would need to be transparent as far as the source code is concerned.

As John pointed out, there is a /check=bounds for C already, but that only covers arrays not "strings".

Greetings, Martin

P.S. So if the next step of Duvel is not Triple, maybe it is Tribble?
Jan van den Ende
Honored Contributor

Re: Overflow

John,


Already done! It's very simple, your compilation statement will be:

$ PASCAL

or

$ ADA

Yes, I would LOVE to be able to agree, but way out in the madhouse called "the real world" for nearly all to-be-ported software it will be:

$ cc


... proven time and again that I *AM* an idiot

maybe, but probably less than I am, and MOST CERTAINLY the average *UX C- or C++-programmer is so in an entirely different dimension.

Martin:

When has a piece of software been ported?

.. well,
for instance when HP supplies us with Apache 2.0
for instance when HP supplies us with DCOM
-- continue the list with your own favorite, plenty of choice!

-- you know, those historic instances where RMS files are not recognised, or, where there are CERT warnings on VMS !!!

examples abound of code that DOES compile, but is unsafe and/or only partly functional at runtime.




And now for the Holy Grail (you know, that mythical, and most probable unattainable, magic Solution-To-Everything)

What I would view as an ideal situation is the C ( & C++ ) compiler to _BY DEFAULT_ add the instructions that give "normal" *UX-style code the robustness and security expected from native VMS developments.

And if that would mean kicking at blatant programming flaws, all the better for that.
If you can demonstrate it to be blatantly flawed, chances are that the original programmer will be gratefull for the improvement. But like Martin wrote, changing the way they are trained to do their job makes Don Quichottes task look minor.
So, THAT would have to be dealt with by the compiler USING THE DEFAULT make-SCRIPT that usually accompanies the stuff.

Generating potentially risky images just for performance reasons should of course remain possible, BUT ONLY AS A CONSCIOUS DECISION, ie, NON-DEFAULT compiler operation.

And oh yeah, I realise I am asking VERY much!
No reason to stop thinking about ways do do some steps in the desired direction, though.


Cheers.

Have one on me.

Jan

Don't rust yours pelled jacker to fine doll missed aches.
Jan van den Ende
Honored Contributor

Re: Overflow

PS Martin,

the next step of Duvel is over the hill, ie, on the way down again!

Cheers.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
Ian Miller.
Honored Contributor

Re: Overflow

I think you are right to target C as it is a language much used and very open to abuse. It is possible to write good code in C as it is in MACRO32 but its very easy not to!

Guard pages around stack frames is and interesting idea. You would be limited to whole 8k pages. I wonder if any allocation of data on the stack at runtime takes place as this would complicate things. I have seen a C library routine ported from another place that did allocate space on the stack (like malloc but memory allocated on the stack).

The heap analyzer is an existing tool which I think does not see enough use but it is a debugging tool not included in production programs.
____________________
Purely Personal Opinion
Jan van den Ende
Honored Contributor

Re: Overflow

Ian,

like I wrote before, my knowledge of both the C language and compiler technology are insufficient to give detailed techie suggestions myself, but it IS this kind of ideas I was hoping to get!

And now.. what about implementabilities?

Cheers.

Have one on me.

Jan
Don't rust yours pelled jacker to fine doll missed aches.
Bojan Nemec
Honored Contributor

Re: Overflow

As told in my previous post, the idea of guard pages arround the stack, cames to my mind when I write it. So I dont know if it can be implemented.
If it can be implemented, it must be implemented very deep in the compiler or maybe in the operating system (a special system service).
Now my ideas how to build such a system service (just ideas!):
When you have a call to a function you do just the same activity (pushing parameters on the stack or create a callg structure (on VAXes)).
Instead of calling the function, call the system service with functions address. The system service must allign the current mode stack to the next 8K boundary and insert in the page table the guard page. The guard page can be a shareable page which is protected against any operation (I dont remember if this is possible, but a kernel mode read only page will be sufficient). The contents of the stack regarding the call (if any) are copyed just after the guard page and the system service calls the function. When finished, the system service removes the guard page and returns to the calling program.
As said, this are only ideas which comes to me when reading this thread.

Bojan
Uwe Zessin
Honored Contributor

Re: Overflow

You can assign a page's protection to PRT$_NA (no access) or not map any memory.
.
Jan van den Ende
Honored Contributor

Re: Overflow

Bojan,

stack guard pages is a nice idea, that has been thought of by others as well:

They __ARE__ implemented in IA64-VMS, and backporting that to AXP-VMS is under investigation, but there is some worry that it _MIGHT_ break existing code, so at best it would be with Switch-on/Switch-off functionality.

Info about IA64-VMS is from the Technical Update Days, about AXP-VMS is from a private discussion with Hoff afterwards.

Guess it is NOT such a bad idea then!

Cheers.

Have one on me.

Jan
Don't rust yours pelled jacker to fine doll missed aches.
Bojan Nemec
Honored Contributor

Re: Overflow

Jan,

That is a good notice. And I am glad that my philosophical thoughts are not allone. The on/off switch is good enought (if not switched off when porting or writing software which is sensible to attacks ;-)

Another thing abbout stack vulnerability is a non-executable stack (as you mentioned in this thread http://forums1.itrc.hp.com/service/forums/questionanswer.do?threadId=721393 ). I think, that this must be implemented on all VMS platforms. I dont think that there are so much self constructing programs which builds the code on the stack and then execute this code. And if this is necesary it can be made in a different mode and not on the stack. Ok, for backward compatibility a special parameter can be implemented.

Bojan
Ian Miller.
Honored Contributor

Re: Overflow

I'm told by Andy Goldstein that noexecute protection was never implemented for VMS on VAX or Alpha. VAXes don't have the seperate execute protection and the fault-on-execute is not set on data sections (and the stack). The only thing that fault-on-execute protection on Alphas was used for was in translated images.
____________________
Purely Personal Opinion
Bojan Nemec
Honored Contributor

Re: Overflow

Ian,

Thanks, I was shure that the noexe flag of the psect does its work. Yust tested and you are right, the code executes fine in a:
.psect data,wrt,noexe

Maybe it will be good to implement it.

Bojan