#include #include #include #include #include #include "mymalloc.h" #include "noaslr.h" struct entry { char *data; unsigned size; }; struct entry *entries; static size_t entry_count; static void run_command_create(unsigned index, unsigned size) { size_t entry_count_new; /* need to allocate more entries? */ if (index >= entry_count) { /* double number of entries until we have enough */ entry_count_new = (entry_count > 256) ? entry_count : 256; while (index >= entry_count_new) entry_count_new *= 2; /* allocate and NULL-initialize new entries */ entries = myrealloc(entries, entry_count_new * sizeof(struct entry)); memset(entries + entry_count, 0, (entry_count_new - entry_count) * sizeof(struct entry)); entry_count = entry_count_new; } entries[index].size = size; entries[index].data = myrealloc(entries[index].data, size); printf("allocated %u bytes for entry %u\n", size, index); } static int check_index(unsigned index) { if (index < entry_count && entries[index].data) return 1; fprintf(stderr, "entry %u not allocated\n", index); return 0; } static void run_command_delete(unsigned index) { if (!check_index(index)) return; myfree(entries[index].data); memset(entries + index, 0, sizeof(struct entry)); printf("deleted entry %u\n", index); } static void run_command_print(unsigned index) { if (!check_index(index)) return; printf("entry %u: ", index); fwrite(entries[index].data, 1, entries[index].size, stdout); printf("\n"); } static void run_command_set(unsigned index, char *data, size_t size) { if (!check_index(index)) return; memcpy(entries[index].data, data, size); printf("set entry %u\n", index); } static int read_skipwhitespace(FILE *file) { int c; do { c = fgetc(file); } while (c != EOF && c != '\n' && isspace(c)); return c; } static char *read_data(FILE *file, size_t *size) { size_t buflen = 0, bufsize = 256; char *buf = mymalloc(bufsize); int c; c = read_skipwhitespace(file); while (c != EOF && c != '\n') { if (buflen >= bufsize) { bufsize *= 2; buf = myrealloc(buf, bufsize); } buf[buflen++] = c; c = fgetc(file); } *size = buflen; return buf; } static int read_empty_line(FILE *file) { int c = read_skipwhitespace(file); return c == EOF || c == '\n'; } static int read_integer(FILE *file, unsigned *value) { int c = read_skipwhitespace(file); if (c < '0' || c > '9') return 0; *value = 0; do { *value = *value * 10 + c - '0'; c = fgetc(file); } while (c >= '0' && c <= '9'); if (c != EOF) ungetc(c, file); return 1; } static void read_line(FILE *file) { int c; do { c = fgetc(file); } while(c != EOF && c != '\n'); } static int read_string(FILE *file, const char *s) { while (*s) { if (fgetc(file) != *s) return 0; s++; } return 1; } static int read_command_create(FILE *file) { unsigned index, size; if (!read_string(file, "reate")) return 0; if (!read_integer(file, &index)) return 0; if (!read_integer(file, &size)) return 0; if (!read_empty_line(file)) return 0; run_command_create(index, size); return 1; } static int read_command_delete(FILE *file) { unsigned index; if (!read_string(file, "elete")) return 0; if (!read_integer(file, &index)) return 0; if (!read_empty_line(file)) return 0; run_command_delete(index); return 1; } static int read_command_print(FILE *file) { unsigned index; if (!read_string(file, "rint")) return 0; if (!read_integer(file, &index)) return 0; if (!read_empty_line(file)) return 0; run_command_print(index); return 1; } static int read_command_set(FILE *file) { char *data; unsigned index; size_t size; if (!read_string(file, "et")) return 0; if (!read_integer(file, &index)) return 0; data = read_data(file, &size); if (!data) return 0; run_command_set(index, data, size); myfree(data); return 1; } static int processcmd(FILE *file) { int c; c = read_skipwhitespace(file); if (c == EOF) return 0; switch (c) { case 'c': if (!read_command_create(file)) break; return 1; case 'd': if (!read_command_delete(file)) break; return 1; case 'p': if (!read_command_print(file)) break; return 1; case 's': if (!read_command_set(file)) break; return 1; } fprintf(stderr, "bad command\n"); read_line(file); return 1; } static void usage(const char *argv0) { printf("usage:\n"); printf(" %s\n", argv0); printf("\n"); printf("commands on stdin:\n"); printf(" create index size - allocate size bytes for entry index\n"); printf(" delete index - deallocate entry index\n"); printf(" print index - print data for entry index\n"); printf(" set index data - set entry index to data\n"); exit(0); } int main(int argc, char **argv, char **envp) { if (argc != 1) usage(argv[0]); while (processcmd(stdin)); return 0; }