Reputation: 1207
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?
Upvotes: 2
Views: 318
Reputation: 3006
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.
Upvotes: 0
Reputation: 153338
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.
Upvotes: 2
Reputation: 179402
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.
Upvotes: 6
Reputation: 21
fgets(output, sizeof(output), fp) reads (sizeof(output) -1) number of characters in this case(otherwise it reads till newline or end of file)
Upvotes: 0