Skip to content

Instantly share code, notes, and snippets.

@pete
Created January 13, 2009 05:40
Show Gist options
  • Save pete/46344 to your computer and use it in GitHub Desktop.
Save pete/46344 to your computer and use it in GitHub Desktop.
/*
cter.c
Elmore wins prize for most hacky, unsafe, ugly semi-implementation of a C
interpreter. Took an hour to write, took almost as long to do a full run of
the stress test. Compared to its trim 202 megs of actual memory used after
21,840 printf()s ran (each from its own separate .so), it seems obscene that
the cost in virtual memory was in excess of 40 gigs (at which point Linux
became angry with me and refused to allow my little program to continue).
Was basically a proof-of-concept for something completely unrelated to
C. Note the lack of calls to dlclose(): this was neither an accident nor
laziness. (All the other things that never got cleaned up, though? Those
were laziness.)
I highly recommend you use rlwrap if you want to run this interactively.
cc -pipe -fPIC -DPIC -rdynamic -o cter cter.c -ldl
-rdynamic and -ldl are the two important ones.
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
/*
We are so unconcerned with buffer overflows that it is ridiculous.
*/
#define BIG_ENOUGH 4096
static int is[1000];
static void *ps[1000];
int *get_is() { return is; }
void **get_ps() { return ps; }
int main(int argc, char *argv[])
{
FILE *outfile;
void (*f)();
void *genhan;
char name[BIG_ENOUGH],
sourcename[4 + BIG_ENOUGH + 2],
soname[4 + BIG_ENOUGH + 3],
cmd[BIG_ENOUGH],
line[BIG_ENOUGH];
unsigned long int i = 1, ttyp = isatty(0);
if(stat("sos", NULL) < 0)
mkdir("sos", 0755);
while(1) {
sprintf(name, "cter%d", i);
sprintf(sourcename, "sos/%s.c", name);
sprintf(soname, "sos/%s.so", name);
if(ttyp) { printf("%4d > ", i); fflush(stdout); }
sprintf(*argv, "cter(%d)", i);
/* I told you we didn't care about buffer overflows. */
if(!gets(line)) { // <-- See?
fprintf(stderr, __FILE__ ":%d: Oops, failgets().\n",
__LINE__);
fflush(stderr);
exit(0);
}
outfile = fopen(sourcename, "w");
if(!outfile) {
fprintf(stderr, __FILE__ ":%d: Oops, failwrite.\n",
__LINE__);
fflush(stderr);
continue;
}
fprintf(outfile,
"#include <stdio.h>\n"
"#include <stdlib.h>\n"
"#include <math.h>\n"
"#include <unistd.h>\n"
"#include <time.h>\n"
"\n"
"int *get_is();\n"
"void *get_ps();\n"
"\n"
"void f() {\n"
"int *is = get_is();\nvoid **ps = get_ps();\n"
"\n"
"\t%s;\n"
"}\n",
line);
fclose(outfile);
sprintf(cmd, "gcc %s -o %s %s "
"-pipe -shared -fPIC -DPIC -DREENTRANT",
getenv("CFLAGS"), soname, sourcename);
// if(ttyp) puts(cmd);
system(cmd);
genhan = dlopen(soname, RTLD_LAZY);
if(!genhan) {
fprintf(stderr, __FILE__
":%d: Oops, failhandle (%s).\n",
__LINE__, dlerror());
fflush(stderr);
continue;
}
f = (void (*)())dlsym(genhan, "f");
if(!f) {
fprintf(stderr, __FILE__ ":%d: Oops, failfunction.\n",
__LINE__);
fflush(stderr);
continue;
}
f();
i++;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment