2

I am currently learning C in one of my courses at the university. Now we have a task to solve and I am not sure how to do it.

The task looks like this: "Is it possible to let this program crash with user inputs? If so, explain this case."

The program we have been given is quite simple and looks like this:

#include <stdio.h>  // Include to use printf, scanf

int main()
{
    // Define buffers to store user name and password
    char username[16];
    char password[16];

    // Read username and password from user input
    printf("Enter your name: ");
    scanf("%s", username);
    printf("Enter your password: ");
    scanf("%s", password);
    printf("[SHOUTING OUT LOUD] Hello, %s!\n", username);

    return 0;
}   

I already found out, that you can make the program print out the password, if you use a username longer than 15 chars. But this is obviously not a crash. So I haven't found a way to crash the program, but somehow I am pretty sure, that there is a way to do this. Does somebody has any idea?

Thanks :)

Mr. Moose
  • 101
  • 8
  • does `ctrl+c` count? – Abhishek Bhagate Jun 05 '20 at 12:05
  • Whoever asked you this question is likely glossing over details or doesn't fully understand C. It appears the intent is for you to overflow the buffers. But that doesn't guarantee a crash. See the answer already posted regarding Undefined Behaviour. – kaylum Jun 05 '20 at 12:08
  • 1
    "*But this is obviously not a crash.*" - Is a segmentation fault runtime error not a crash in your terms? – RobertS supports Monica Cellio Jun 05 '20 at 12:14
  • 1
    Well, theoretically speaking the crash "can" happen. But writing an username long enough to overwrite the stack area, especially the return addresses WILL cause a crash. – Roberto Caboni Jun 05 '20 at 12:24
  • I already tied entering more then 15 chars and in my case there was no error or crash. The printed result was not correct, but I already expected that. So what I tried next was to enter a huge number of chars and now at some point my program stops working and tells me `*** stack smashing detected ***: terminated Aborted`... This is more likely what i was looking for. But is there a reason, why it happens at a specific number of chars which are also higher, then the 15+15 chars of my arrays? – Mr. Moose Jun 05 '20 at 12:43
  • @Mr.Moose Apparently you edited the previous comment I was going to answer. You wrote about the crash occurring at the 25th character beyond the size of password, right? Actually it perfectly makes sense: 16 characters overwrite the value previously set for "username". 8 bytes are actually the implicit parameters of the main function (`int argc`, 4 bytes, and `void ** argv`, 4 bytes). Going beyond them you overwrite the main return address, invading _"OS's lands". – Roberto Caboni Jun 05 '20 at 13:43
  • The one above is just a _tentative_ explanation, as `main()` is a very special function I'm not expert with (otherwise I would have written an answer myself). What I would like to explain is that the answer to the question _"Is it possible to let this program crash with user inputs? If so, explain this case."_ is **yes. always**. The _undefined behavior_ explanation is correct, because the standards doesn't define the behavior. But given the (compiler-HW platform-OS) tuple the behavior is actually defined. And in any system writing enough bytes to _hyperspace_ will always lead to a crash... – Roberto Caboni Jun 05 '20 at 13:49
  • ... and by changing the context, it will just change the number of out of bounds bytes required to cause the crash, but the answer will always be yes. – Roberto Caboni Jun 05 '20 at 13:51
  • Okay, thx everybody. Just one more thing. My next task would be to correct the code and improve the security issues. But if I got you right, there will always be an input that is too big. Does that mean, that you can expand the input size, but never be sure, that it is big enough? – Mr. Moose Jun 05 '20 at 14:27

3 Answers3

6

Entering a username or password longer than 15 characters can crash the program, it's just not guaranteed to do so.

When you write past the bounds of an array, you invokes undefined behavior. Loosely speaking, that means you can't make any assumptions about what your program will do. It may crash, it may output strange results, or it may appear to work properly.

Just because the program could crash doesn't necessarily mean it will.


That being said, given the way most compilers you're likely to come across work, you're more likely to get a crash the longer the string you enter.

Local variables are typically allocated on the stack adjacent to each other. For example, suppose username comes immediately before password on the stack. If you enter in a 20 character name for the username, it will write past username into password and username will not contain a null terminating byte. When you then enter a password, it will overwrite any characters of the username after the first 16. Then when you print username, you'll see the first 16 characters of what you entered followed by the password.

Now suppose you enter in 100 characters for the username. This will write past username and past password and will most likely overwrite the return address for main. Then when main attempts to return is reads a bogus address, and attempting to jump to that address is what causes the crash.

But again, this is all very system specific, and can vary based on the type/order you place variables, which functions you call, and what optimization setting you use to compile, among others.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    Doesn´t a write operation beyond the bounds of the buffer *always* end up in a segmentation fault error at run-time? – RobertS supports Monica Cellio Jun 05 '20 at 12:20
  • 3
    @RobertSsupportsMonicaCellio, no it won't. There may be unused memory after the array that can be written to. Although illegal, in that case it won't crash the program. – Paul Ogilvie Jun 05 '20 at 12:23
  • @PaulOgilvie I´m not so sure about this. AFAIK the error already shows up at the *attempt* to write beyond the bounds. -> https://stackoverflow.com/a/2346816/12139179 – RobertS supports Monica Cellio Jun 05 '20 at 12:29
  • @RobertSsupportsMonicaCellio No, see my edit for an example of what could happen. – dbush Jun 05 '20 at 12:31
  • 2
    @RobertSsupportsMonicaCellio OP says "I already found out, that you can make the program print out the password, if you use a username longer than 15 chars". That is a clear example of an observed case of not crashing even when a buffer is overflowed. – kaylum Jun 05 '20 at 12:35
  • @RobertSsupportsMonicaCellio it is called _undefined behavior_ for a reason. If "a write operation beyond the bounds of the buffer always end up in a segmentation fault" were true, that would be _defined behavior_. C does not require a seg fault anywhere. – chux - Reinstate Monica Jun 05 '20 at 12:36
  • @dbsuh Hi, thanks. Is there a way to determine (except just trying) how many chars I have to enter. What is the size of the return adress. So how many chars do I need to enter, before I overwrite it? – Mr. Moose Jun 05 '20 at 12:48
  • @Mr.Moose Again, that's very system specific. You just need to try various inputs to see what will make it crash. – dbush Jun 05 '20 at 12:56
  • @dbush OP question was mainly about _the possibility_ to cause a crash rather than the precise quantification of the number of bytes causing it. So, IMHO, even if the _undefined behavior explanation_ is formally correct, the short answer is **"yes, it is possible"**. See my comments to OP if interested to my arguments. – Roberto Caboni Jun 05 '20 at 13:56
  • PS: anyway you basically filled the gap with your edit, even if with less emphasis than the one I would have used. So I gave up in writing my answer and upvoted yours. – Roberto Caboni Jun 05 '20 at 13:58
1

It won't necessarily crash if you give an input of more than 15 characters in every environment. It depends on whether it uses an memory on the system that's inaccessible to it.

Undefined Behavior

  • If the contiguous areas of memory following the memory assigned to your string are empty or are currently unused/unclaimed by any other process at the time you run your program, then writing to them will show no effect.

  • But when you run it some other time, it is possible that the memory location following the allocated area is occupied/in use by some other process/program, which may crash your program.

  • Since, this behavior is unpredictable, it is known as undefined behavior.

Remember, C doesn't do out of memory bounds checking which is why it runs fine. But your program may crash anytime when you give input > 15 characters. In other programming languages, with strict checking, you will probably get an exception in this case.

Hope this helps !

Note : On windows, ctrl+C is your best shot if you are willing to consider this as crash. Rest all times, it will be indeterminable if your program would crash.

Community
  • 1
  • 1
Abhishek Bhagate
  • 5,583
  • 3
  • 15
  • 32
  • "occupied/in use by some other process/program": that cannot be true on modern architectures because each program/process will be given its own (virtual) memory. – Paul Ogilvie Jun 05 '20 at 12:25
  • if you define something like -`char username[16]`, username will be allocated 16 bytes of memory somewhere in your storage. But when we enter input of more than 16 char, it gets written into memory immediately following the end of allocated memory. That memory may be used/unused and depending on that, the program would either run or abnormally terminate. That's what I always thought about it. Correct me if I am wrong anywhere – Abhishek Bhagate Jun 05 '20 at 12:30
  • You should make that second bullet more clear. As written, it is what I commented about as incorrect. It may be in use by another _part_ of the program, but not by another program. – Paul Ogilvie Jun 05 '20 at 12:33
  • I am not clear on it. Is there no chance that it could be part of other program in any case? – Abhishek Bhagate Jun 05 '20 at 12:38
  • "C doesn't do out of memory bounds checking" may mis-lead. C can do out of memory bounds checking - it is just not required. – chux - Reinstate Monica Jun 05 '20 at 12:39
  • @chux-ReinstateMonica > C don’t provide any specification which deal with problem of accessing invalid index. And right, did the edit to 15. – Abhishek Bhagate Jun 05 '20 at 12:43
  • @PaulOgilvie _"that cannot be true on modern architectures because each program/process will be given its own (virtual) memory"_ in that case it would be an even more explicit crash, as trespassing the allowed virtual memory of the process (segment) would lead to segmentation fault. – Roberto Caboni Jun 05 '20 at 13:36
  • @RobertoCaboni, the crash will be fine, but that does not affect the memory of another process or program. – Paul Ogilvie Jun 05 '20 at 14:51
  • @PaulOgilvie Sure! My note was about the fact Abhishek mentioned this as the cause for making **your** program crash; no mention about the interaction with the other program. ;) (forgive my _lawyer mode_. I'll end it here. :) ) – Roberto Caboni Jun 05 '20 at 14:56
0

But this is obviously not a crash. So I haven't found a way to crash the program, but somehow I am pretty sure, that there is a way to do this. Does somebody has any idea?

Well, if you really need a 'full crash' try:

MyProg < SomeLargeFile
Danny_ds
  • 11,201
  • 1
  • 24
  • 46