I have always been interested with compiler design. From LALR parsers in the curriculum to GIMPLE trees in gcc, it's been quite an amazing feeling of learning things. How one trusts a particular compiler itself is a thing, very few would have actually thought off. Pramode sir, highlighted that fact in one of his posts here.
That made me think for 5 minutes and, I came up with a ruby code to generate a C-program with a deep nesting level. I wrote a recursive program, and for nesting level > 3000, I got stack overflow error. Stupid Ruby. I then implemented the same logic in C. Here is the code.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
int fd;
void init_prog(int nesting_count)
{
fd = open("crash_gcc.c", O_CREAT | O_RDWR, 0666);
char *buffer = "#include <stdio.h>\n#include \
<stdlib.h>\n\nint main()\n{\n\t";
write(fd, buffer, strlen(buffer));
}
void define_variables(int nesting_count)
{
char *buffer = "int i;\n";
write(fd, buffer, strlen(buffer));
}
void write_nesting(int n, int n_actual, char *tab_buf)
{
int i;
char *buffer = "for(i=0;i < 10000; i++) {\n";
write(fd, tab_buf, n_actual-n+1);
write(fd, buffer, strlen(buffer));
if(n > 0) write_nesting(n-1, n_actual, tab_buf);
write(fd, tab_buf, n_actual-n+1);
write(fd, "}\n", 2);
}
void uninit_prog()
{
write(fd, "}\n", 2);
close(fd);
}
int main(int argc, char *argv[])
{
char *tab_buf;
if(argc < 2) {
printf("Run as ./a.out <count>\n");
exit(EXIT_FAILURE);
}
int nesting_count = atoi(argv[1]), i;
tab_buf = (char *)calloc(1, nesting_count*sizeof(char) + 1);
for(i = 0;i < (nesting_count+1); i++) *(tab_buf+i) = '\t';
init_prog(nesting_count);
define_variables(nesting_count);
write_nesting(nesting_count-1, nesting_count-1, tab_buf);
uninit_prog();
free(tab_buf);
return 0;
}
When you run this program with an argument (for e.g:- ./a.out 10), it generates another file `crash_gcc.c`, which consists of a nesting level as deep as the argument provided to the program. Try out the program with argument as 1, 5, 10, 100, 1000, and so on....
Try compiling the program for nesting level greater than 15000, and you will see gcc crashing. It may work for level lesser than 15000 also. Try it out.
That was fun...