简体   繁体   中英

How come my C program doesn't crash when I overflow an allocated array of characters?

I have a simple C file I/O program which demonstrates reading a text file, line-by-line, an outputting its contents to the console:

/**
* simple C program demonstrating how
* to read an entire text file
*/

#include <stdio.h>
#include <stdlib.h>

#define FILENAME "ohai.txt"

int main(void)
{
    // open a file for reading
    FILE* fp = fopen(FILENAME, "r");

    // check for successful open
    if(fp == NULL)
    {
        printf("couldn't open %s\n", FILENAME);
        return 1;
    }

    // size of each line
    char output[256];

    // read from the file
    while(fgets(output, sizeof(output), fp) != NULL)
        printf("%s", output);

    // report the error if we didn't reach the end of file
    if(!feof(fp))
    {
        printf("Couldn't read entire file\n");
        fclose(fp);
        return 1;
    }

    // close the file
    fclose(fp);
    return 0;
   }

It looks like I've allocated an array with space for 256 characters per line (1024 bytes bits on a 32-bit machine). Even when I fill ohai.txt with more than 1000 characters of text on the first line, the program doesn't segfault, which I assumed it would, since it overflowed the allocated amount of space available to it designated by the output[] array.

My hypothesis is that the operating system will give extra memory to the program while it has extra memory available to give. This would mean the program would only crash when the memory consumed by a line of text in ohai.txt resulted in a stackoverflow.

Could someone with more experience with C and memory management support or refute my hypothesis as to why this program doesn't crash, even when the amount of characters in one line of a text file is much larger than 256?

You're not overflowing anything here: fgets won't write more than sizeof(output) characters to the buffer, and therefore will not overflow anything (see the documentation ).

However, if you do overflow a buffer, you get undefined behaviour. According to the C spec, the program may do anything : crash, not crash, silently destroy important data, accidentally call rm -rf / , etc. So, don't expect a program to crash if you invoke UB.

OP's program did not crash because no buffer overflow occurred.

while(fgets(output, sizeof(output), fp) != NULL)
  printf("%s", output);

The fgets() nicely read a group of char up to a count or 255 or a \\n . Then printf("%s" ... nicely printed them out. This repeated until no more data/

No crash, no overflow, no runs, no hits , no errors.

fgets(output,sizeof(output),fp)读取(sizeof(输出)-1)这种情况下的字符数(否则读取直到换行符或文件末尾)

Explanation of stacks and why this might not segfault even if you actually did overflow (and as others have pointed out the code as written will not)

Your stack pointer starts at some address say 0x8000000 then the runtime calls main and it'll move down a bit (there may be other stuff up there so we don't know how much stuff is on the stack at the start of main), then main will move the stack pointer some more for all it's local variables. So at this point your array will have an address that is more than 256 bytes below 0x8000000 and you won't get a segfault unless you run all the way over all of main's stack frame and the stack frames of whatever other C runtime stuff called main.

So for the sake of simplicity assume your array ends up with it's base address at 0x7fffd00 that's 768 bytes below 0x8000000 meaning at a minimum you'd have to overflow by that much to get a segfault, (well you'd probably get a segfault when main returns or when you call feof, because you filled your stack frame with random characters, but we're talking about segfaults inside fgets()) but even that's not gaurenteed if something writable is mapped to the page above your stack (unlikely most OSs avoid doing that so you'll get a segfault if you overflow far enough)

If the stack runs the other way (ie: growing upward) you'd have to run over the entirety of the maximum size stack, which in userspace is usually quite large (Default on Linux for 32bit x86 is 2MB) but I'm pretty sure x86 stacks grow downward so that's not likely for your case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM