| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| #include "afl-fuzz.h" |
| #include "gramfuzz.h" |
| #ifdef _GNU_SOURCE |
| #undef _GNU_SOURCE |
| #endif |
| #define _GNU_SOURCE |
| #include <sys/mman.h> |
| |
| /* Dynamic Array for adding to the input repr |
| * */ |
| void initArray(Array *a, size_t initialSize) { |
| |
| a->start = (terminal *)calloc(1, sizeof(terminal) * initialSize); |
| a->used = 0; |
| a->size = initialSize; |
| a->inputlen = 0; |
| |
| } |
| |
| void insertArray(Array *a, int state, char *symbol, size_t symbol_len, |
| int trigger_idx) { |
| |
| // a->used is the number of used entries, because a->array[a->used++] updates |
| // a->used only *after* the array has been accessed. Therefore a->used can go |
| // up to a->size |
| terminal *term_ptr; |
| if (a->used == a->size) { |
| |
| a->size = a->size * sizeof(terminal); |
| a->start = (terminal *)realloc(a->start, a->size * sizeof(terminal)); |
| |
| } |
| |
| // Add the element |
| term_ptr = &a->start[a->used]; |
| term_ptr->state = state; |
| term_ptr->symbol = symbol; |
| term_ptr->symbol_len = symbol_len; |
| term_ptr->trigger_idx = trigger_idx; |
| |
| // Increment the pointer |
| a->used += 1; |
| a->inputlen += symbol_len; |
| |
| } |
| |
| void freeArray(Array *a) { |
| |
| terminal *ptr; |
| for (int x = 0; x < a->used; x++) { |
| |
| ptr = &a->start[x]; |
| free(ptr); |
| |
| } |
| |
| a->start = NULL; |
| a->used = a->size = 0; |
| |
| } |
| |
| /* Dynamic array for adding indices of states/recursive features |
| * Source: |
| * https://stackoverflow.com/questions/3536153/c-dynamically-growing-array |
| */ |
| void initArrayIdx(IdxMap *a, size_t initialSize) { |
| |
| a->array = (int *)malloc(initialSize * sizeof(int)); |
| a->used = 0; |
| a->size = initialSize; |
| |
| } |
| |
| void insertArrayIdx(IdxMap *a, int idx) { |
| |
| // a->used is the number of used entries, because a->array[a->used++] updates |
| // a->used only *after* the array has been accessed. Therefore a->used can go |
| // up to a->size |
| if (a->used == a->size) { |
| |
| a->size *= 2; |
| a->array = (int *)realloc(a->array, a->size * sizeof(int)); |
| |
| } |
| |
| a->array[a->used++] = idx; |
| |
| } |
| |
| void freeArrayIdx(IdxMap *a) { |
| |
| free(a->array); |
| a->array = NULL; |
| a->used = a->size = 0; |
| |
| } |
| |
| /* Dynamic array for adding potential splice points |
| */ |
| void initArraySplice(SpliceCandArray *a, size_t initialSize) { |
| |
| a->start = (SpliceCand *)malloc(initialSize * sizeof(SpliceCand)); |
| a->used = 0; |
| a->size = initialSize; |
| |
| } |
| |
| void insertArraySplice(SpliceCandArray *a, Candidate *candidate, int idx) { |
| |
| // a->used is the number of used entries, because a->array[a->used++] updates |
| // a->used only *after* the array has been accessed. Therefore a->used can go |
| // up to a->size |
| SpliceCand *candptr; |
| if (a->used == a->size) { |
| |
| a->size = a->size * sizeof(SpliceCand); |
| a->start = (SpliceCand *)realloc(a->start, a->size * sizeof(SpliceCand)); |
| |
| } |
| |
| // Add the element |
| candptr = &a->start[a->used]; |
| candptr->splice_cand = candidate; |
| candptr->idx = idx; |
| a->used += 1; |
| |
| } |
| |
| void freeArraySplice(IdxMap *a) { |
| |
| free(a->array); |
| a->array = NULL; |
| a->used = a->size = 0; |
| |
| } |
| |
| int fact(int n) { |
| |
| int i, f = 1; |
| for (i = 1; i <= n; i++) { |
| |
| f *= i; |
| |
| } |
| |
| return f; |
| |
| } |
| |
| /* Uses the walk to create the input in-memory */ |
| u8 *unparse_walk(Array *input) { |
| |
| terminal *term_ptr; |
| int offset = 0; |
| u8 * unparsed = (u8 *)malloc(input->inputlen + 1); |
| term_ptr = &input->start[offset]; |
| strcpy(unparsed, term_ptr->symbol); |
| offset += 1; |
| while (offset < input->used) { |
| |
| term_ptr = &input->start[offset]; |
| strcat(unparsed, term_ptr->symbol); |
| offset += 1; |
| |
| } |
| |
| return unparsed; |
| |
| } |
| |
| /*Dump the input representation into a file*/ |
| void write_input(Array *input, u8 *fn) { |
| |
| FILE *fp; |
| // If file already exists, then skip creating the file |
| if (access(fn, F_OK) != -1) { return; } |
| |
| fp = fopen(fn, "wbx+"); |
| // If the input has already been flushed, then skip silently |
| if (fp == NULL) { |
| |
| fprintf(stderr, "\n File '%s' could not be open, exiting\n", fn); |
| exit(1); |
| |
| } |
| |
| // Write the length parameters |
| fwrite(&input->used, sizeof(size_t), 1, fp); |
| fwrite(&input->size, sizeof(size_t), 1, fp); |
| fwrite(&input->inputlen, sizeof(size_t), 1, fp); |
| |
| // Write the dynamic array to file |
| fwrite(input->start, input->size * sizeof(terminal), 1, fp); |
| // printf("\nUsed:%zu Size:%zu Inputlen:%zu", input->used, input->size, |
| // input->inputlen); |
| fclose(fp); |
| |
| } |
| |
| Array *parse_input(state *pda, FILE *fp) { |
| |
| terminal *term; |
| state * state_ptr; |
| trigger * trigger; |
| int trigger_idx; |
| Array * input = (Array *)calloc(1, sizeof(Array)); |
| |
| // Read the length parameters |
| fread(&input->used, sizeof(size_t), 1, fp); |
| fread(&input->size, sizeof(size_t), 1, fp); |
| fread(&input->inputlen, sizeof(size_t), 1, fp); |
| |
| terminal *start_ptr = (terminal *)calloc(input->size, sizeof(terminal)); |
| if (!start_ptr) { |
| |
| fprintf(stderr, "alloc failed!\n"); |
| return NULL; |
| |
| } |
| |
| // Read the dynamic array to memory |
| fread(start_ptr, input->size * sizeof(terminal), 1, fp); |
| // Update the pointers to the terminals since they would have |
| // changed |
| int idx = 0; |
| while (idx < input->used) { |
| |
| terminal *term = &start_ptr[idx]; |
| // Find the state |
| state_ptr = pda + term->state; |
| // Find the trigger and update the terminal address |
| trigger_idx = term->trigger_idx; |
| trigger = (state_ptr->ptr) + trigger_idx; |
| term->symbol = trigger->term; |
| idx += 1; |
| |
| } |
| |
| input->start = start_ptr; |
| // printf("\nUsed:%zu Size:%zu Inputlen:%zu", input->used, input->size, |
| // input->inputlen); |
| |
| return input; |
| |
| } |
| |
| // Read the input representation into memory |
| Array *read_input(state *pda, u8 *fn) { |
| |
| FILE *fp; |
| fp = fopen(fn, "rb"); |
| if (fp == NULL) { |
| |
| fprintf(stderr, "\n File '%s' does not exist, exiting\n", fn); |
| exit(1); |
| |
| } |
| |
| Array *res = parse_input(pda, fp); |
| fclose(fp); |
| return res; |
| |
| } |
| |