There's a bit of confusion going on here. I'll try to clear it up, but in the future everybody please
- don't jump to premature conclusions. Stick to the observations first. If you then want to speculate on what's going on, go ahead, but don't omit the facts for this.
- when describing observed behaviour, *ALWAYS*, if at all possible, include *COMPLETE* test code that shows the behaviour.
Richard D. Jackson wrote:
On Thu, 2003-02-13 at 01:27, Frank Heckenbach wrote:
<snip> > In this case what gpc does is truncate the return value to fit into > myStr. Other words this does not cause a compiler error so the compiler > sees these two strings as being equivlant even though that is not the > case.
My previous reply to Chuck's mail should have made this clear.
Did not get that one until after I wrote my reply.
Sure, and I didn't see your comment until I wrote mine -- just wanted to avoid some confusion ...
<snip> > What is interesting is that. > Given > > var > buff : String (255); > > I can stuff 30925 chars into it after that majic number I get a > segfault.
I can't. The following stops at 255.
program Foo;
var buff : String (255);
counter : Integer;
begin buff := '';
counter := 1;
repeat buff := buff + ' '; WriteLn (Length (buff))
WriteLn ( counter ); counter := counter + 1;
until False end.
Here even though the Length of buff will stay 255 after the 255th iteration counter will go to 30951 before the segfault. Which means the sting buffer is going out of bounds.
No, it isn't. Actually, the string buffer is static and doesn't go anywhere. What you might mean is a string index going out of bounds, but no string indexing is done, so this isn't happening, either.
What really happens is:
- The string is silently truncated. This may not always be desirable, but is permitted by the standard (cf. my reply to Chuck), and it's no security hole.
- A known bug, as listed in the to-do list: "possible stack overflow when using string concatenation in a loop [...]". A stack overflow manifests itself as a segfault on many systems, but AFAIK, it's no security problem, either (at least on systems that have a slightly sane memory management).
Actually, I had thought of the latter, but since you said "I can stuff 30925 chars into it", I thought it wasn't that, so I didn't mention it previously.
If what you mean is treating the string as an array of char and indexing out of range, this would be a matter of range-checking(*) -- I'm not sure if you mean this, that's why it's always a good idea to include some example code!
Here is what I used but note it is slopy as I was trying out other things as well. [...]
OK, that's the same issue (`Concat' and `+' for strings are basically the same).
Prof. A Olowofoyeku (The African Chief) wrote:
Richard D. Jackson wrote:
What is interesting is that. Given
var buff : String (255);
I can stuff 30925 chars into it after that majic number I get a segfault. So what is happening here? If I suround a string with other vars they are not getting overwriten wich is a good thing but I still wonder why it did not segfault at 256.
That is just chance. Take the same program to another PC running the same OS (or compile for another OS) and you might well get the segfault in a different place.
I also don't think that you can rely on other variables not being overwritten. Something is being overwritten.
If it was really an out-of-bounds (string or array) index, as I had conjectured, this would be true. For the stack overflow bug, AFAIK there's no danger of overwriting something else (just a program crash ;-).
Richard D. Jackson wrote:
I'd like to see range checking available as an option but I think the work to integrate gpc with gcc is more important.
I agree with this as a carfull programer will not allow this to happen. The one place where you do need range checking is input which you can get around by using a libc function I forget the exact function names but I know they are there in libc due to all of the buffer overflow security issues.
Again, some confusion. Range checking on input would apply to reading integer subranges (e.g., `var Foo: 1 .. 10; [...] ReadLn (Foo)'). You can get around this by explicit tests (`if (Foo < 1) or (Foo > 10) then Halt (1)'), or to avoid runtime errors, even on non-numeric input, reading into a string, and using `Val'.
But I don't think you mean this, but rather string capacity checking during input. This does happen, so the dreaded string overflows in C as in gets() are really not applicable.
Frank