If, as you say, you only use system calls, you can leave using the entire heap as a buffer.
#include <unistd.h> #include <signal.h> #include <stdio.h> #include <sys/types.h> #include <fcntl.h> size_t sz; void fix(x){signal(SIGSEGV,fix);sbrk(sz *= 2);} int main() { sz = getpagesize(); signal(SIGSEGV,fix); char *buf = sbrk(sz); int fd = open("filename", O_RDWR); read(fd, buf, -1); }
But if you call a library function that uses malloc, Kablooey!
The brk and sbrk give you direct access to the same heap that malloc uses. But without any of the overhead. And without any malloc features like free , realloc . sbrk is called with a size in bytes and returns void * . brk is called with the value of the pointer (i.e. you just imagine that the pointer exists and declares it to be brk in some way) and returns void * .
Using brk or sbrk to allocate memory, it uses the same space that malloc will try to install and use when it first calls malloc or realloc . And many library functions use malloc under the hood, so there are many ways to break this code. This is a very strange and interesting area.
The signal handler here is also very dangerous. This gives you automatic unlimited space, but, of course, if you encounter any other segmentation violation, such as dereferencing the NULL pointer, the handler cannot fix it, and it can no longer crash. Thus, this can send the program into an unpleasant cycle: retry access to memory, allocate more space, retry access to memory, allocate more space.
source share