Question Authors' Forum

no consequences of array boundary violation

Picture of Jesko Treffler
no consequences of array boundary violation
by Jesko Treffler - Thursday, 19 November 2015, 3:53 AM
In my exercise, coderunner seems to be very forgiving for corruptions around the stack.

I designed an exercise in which students should compare to strings given to the program via the standard input.
For example:

My template:

#include <stdio.h>
#define MAX_LAENGE 10


so the students are asked to code the main function, preferably using scanf to get these two inputs and compare them.
my sample answer is:

int main() {
    char chrEingabe1[MAX_LAENGE];
    char chrEingabe2[MAX_LAENGE];
    int intLaenge1, intLaenge2,intReturnWert=0,intCounter=0;
    scanf("%s", chrEingabe1);
    while(chrEingabe1[intLaenge1]!='\0') intLaenge1++;
    while(chrEingabe2[intLaenge2]!='\0') intLaenge2++;
            if(chrEingabe1[intCounter]!=chrEingabe2[intCounter]) intReturnWert = 2;
    else intReturnWert = 1;
    return intReturnWert;

Entering this in a normal IDE it should spit out an error, cause Raumschiff1 and Raumschiff2 are both 11signs long. Xcode gives me those error messages as soon as the arrays are smaller then 12 for Raumschiff1 and Raumschiff2

But Coderunner won't moan and would give you a "2" as a result (which is my definition of Raumschiff1 and Raumschiff2 are not the same signs).
If you reduce the size of the arrays manually, it starts complaining when entering 8 instead of MAX_LAENGE :
***Runtime error***
*** stack smashing detected ***: ./prog.c.exe terminated
/var/www/html/jobe/application/libraries/../../runguard/runguard: warning: command terminated with signal 6

But even more suprisingly if you enter 2 instead of MAX_LAENGE there is no error message at all.

Picture of Richard Lobb
Re: no consequences of array boundary violation
by Richard Lobb - Thursday, 19 November 2015, 11:49 AM

Hi Jesko

What you're seeing there is standard GNU C behaviour, at least under Linux. I get exactly the same results as you running your program within the geany mini-IDE.

Using scanf with a %s format is inherently unsafe. The scanf function is passed just a pointer to the destination address and (usually, anyway) has no way of knowing how much space is available. I'm surprised that xcode is apparently able to detect that buffer overflow. The compiler could be secretly passing some additional information to the scanf function, or setting up some guard value at the end of all arrays to detect the overflow, but I can't see any reference on the web to such a capability.

I'd suggest using fgets to read strings, rather than scanf.

I agree it's odd that stack smashing isn't detected when you reduce the array size to 2 but I always tell my students that once you corrupt the stack, anything may happen. So I guess this is one sort of "anything"! I could inspect the generated code to see why, but I'd rather you just switched to using a safe function like fgets :-)


Picture of Jesko Treffler
Re: no consequences of array boundary violation
by Jesko Treffler - Friday, 20 November 2015, 2:55 AM

Hi Richard

I learned C on Visual Studio, and there either starting the programm in the IDE or Commandline would give you an error message and the programm will be terminated. I think depending on which areas of the memory you are corrupting this happens immediately or at the end of the code (while going through it step-by-step), using Xcode is new for me as well, but since I have to work on Mac this was my only option to test the code quickly. 

Installing Netbeans with gdb is complicated thanks to Apple only supporting their weird lldb.

The main reason for my post was that odd behaviour when reducing those arrays to 2 or 3, that confused me most.

I haven't thought that it is depending on the compiler, and I just started to work with coderunner, trying to figure out the possibilities.
I'll have to leave it to the lab-advisers to make students aware of careful handling with arrays  and stack corruption, as you say anything can happen, hard to find test scenarios for anything^^.


Picture of Richard Lobb
Re: no consequences of array boundary violation
by Richard Lobb - Friday, 20 November 2015, 8:45 PM

Hi Jesko

I looked further into why the stack smashing detection seems to disappear when you reduce the size of your char arrays to 2 or 3. If I look at the generated code, it seems the gcc compiler stops inserting the stack-smashing detection code when you reduce the size of the arrays below 4.

I was so puzzled by this that I emailed when of the staff members here, Michael Hayes, who once worked on the gcc compiler. He checked the gcc source code and discovered a bit of code that explicitly turns off stack-smashing detection when arrays fit within a single integer. Why they do that is anybody's guess. A gcc bug, perhaps?

Nothing to do with CodeRunner, but interesting, eh?!

Certainly your lab advisers need to make students very aware of buffer-overflow risks, and also problems arising from uninitialised variables. That's part of the "fun" of learning C. Uninitialised variable problems are particularly common when testing C functions in CodeRunner as the default C_function question type tries to package all the test cases into a single run using the combinator template. The student's function thus gets called repeatedly in the same run, so if they don't explicitly initialise their variables their code breaks. An excellent lesson for them, but I do get a bit sick of their telling me "my code works fine when I run it on my machine".

Of course, you could turn off the combinator template, but that just hides the problem, which could still occur even if the function were called only once. It's better to highlight the issue, I think.