int yr_parser_emit_with_arg_reloc( yyscan_t yyscanner, int8_t instruction, int64_t argument, int8_t** instruction_address) { void* ptr; int result = yr_arena_write_data( yyget_extra(yyscanner)->code_arena, &instruction, sizeof(int8_t), (void**) instruction_address); if (result == ERROR_SUCCESS) result = yr_arena_write_data( yyget_extra(yyscanner)->code_arena, &argument, sizeof(int64_t), &ptr); if (result == ERROR_SUCCESS) result = yr_arena_make_relocatable( yyget_extra(yyscanner)->code_arena, ptr, 0, EOL); return result; }
int yr_parser_emit_with_arg_reloc( yyscan_t yyscanner, uint8_t instruction, void* argument, uint8_t** instruction_address, void** argument_address) { int64_t* ptr = NULL; int result; DECLARE_REFERENCE(void*, ptr) arg; memset(&arg, 0, sizeof(arg)); arg.ptr = argument; result = yr_arena_write_data( yyget_extra(yyscanner)->code_arena, &instruction, sizeof(uint8_t), (void**) instruction_address); if (result == ERROR_SUCCESS) result = yr_arena_write_data( yyget_extra(yyscanner)->code_arena, &arg, sizeof(arg), (void**) &ptr); if (result == ERROR_SUCCESS) result = yr_arena_make_relocatable( yyget_extra(yyscanner)->code_arena, ptr, 0, EOL); if (argument_address != NULL) *argument_address = (void*) ptr; return result; }
int yr_arena_load_stream( YR_STREAM* stream, YR_ARENA** arena) { YR_ARENA_PAGE* page; YR_ARENA* new_arena; ARENA_FILE_HEADER header; uint32_t reloc_offset; uint8_t** reloc_address; uint8_t* reloc_target; int result; if (yr_stream_read(&header, sizeof(header), 1, stream) != 1) return ERROR_INVALID_FILE; if (header.magic[0] != 'Y' || header.magic[1] != 'A' || header.magic[2] != 'R' || header.magic[3] != 'A') { return ERROR_INVALID_FILE; } if (header.size < 2048) // compiled rules are always larger than 2KB return ERROR_CORRUPT_FILE; if (header.version != ARENA_FILE_VERSION) return ERROR_UNSUPPORTED_FILE_VERSION; result = yr_arena_create(header.size, 0, &new_arena); if (result != ERROR_SUCCESS) return result; page = new_arena->current_page; if (yr_stream_read(page->address, header.size, 1, stream) != 1) { yr_arena_destroy(new_arena); return ERROR_CORRUPT_FILE; } page->used = header.size; if (yr_stream_read(&reloc_offset, sizeof(reloc_offset), 1, stream) != 1) { yr_arena_destroy(new_arena); return ERROR_CORRUPT_FILE; } while (reloc_offset != 0xFFFFFFFF) { if (reloc_offset > header.size - sizeof(uint8_t*)) { yr_arena_destroy(new_arena); return ERROR_CORRUPT_FILE; } yr_arena_make_relocatable(new_arena, page->address, reloc_offset, EOL); reloc_address = (uint8_t**) (page->address + reloc_offset); reloc_target = *reloc_address; if (reloc_target != (uint8_t*) (size_t) 0xFFFABADA) *reloc_address += (size_t) page->address; else *reloc_address = 0; if (yr_stream_read(&reloc_offset, sizeof(reloc_offset), 1, stream) != 1) { yr_arena_destroy(new_arena); return ERROR_CORRUPT_FILE; } } *arena = new_arena; return ERROR_SUCCESS; }
int yr_arena_load( const char* filename, YR_ARENA** arena) { FILE* fh; YR_ARENA_PAGE* page; YR_ARENA* new_arena; ARENA_FILE_HEADER header; int32_t reloc_offset; uint8_t** reloc_address; uint8_t* reloc_target; long file_size; int result; fh = fopen(filename, "rb"); if (fh == NULL) return ERROR_COULD_NOT_OPEN_FILE; fseek(fh, 0, SEEK_END); file_size = ftell(fh); fseek(fh, 0, SEEK_SET); if (fread(&header, sizeof(header), 1, fh) != 1) { fclose(fh); return ERROR_INVALID_FILE; } if (header.magic[0] != 'Y' || header.magic[1] != 'A' || header.magic[2] != 'R' || header.magic[3] != 'A') { fclose(fh); return ERROR_INVALID_FILE; } if (header.size >= (uint32_t)file_size) { fclose(fh); return ERROR_CORRUPT_FILE; } if (header.version > ARENA_FILE_VERSION) { fclose(fh); return ERROR_UNSUPPORTED_FILE_VERSION; } result = yr_arena_create(header.size, 0, &new_arena); if (result != ERROR_SUCCESS) { fclose(fh); return result; } page = new_arena->current_page; if (fread(page->address, header.size, 1, fh) != 1) { fclose(fh); yr_arena_destroy(new_arena); return ERROR_CORRUPT_FILE; } page->used = header.size; if (fread(&reloc_offset, sizeof(reloc_offset), 1, fh) != 1) { fclose(fh); yr_arena_destroy(new_arena); return ERROR_CORRUPT_FILE; } while (reloc_offset != -1) { yr_arena_make_relocatable(new_arena, page->address, reloc_offset, EOL); reloc_address = (uint8_t**) (page->address + reloc_offset); reloc_target = *reloc_address; if (reloc_target != (uint8_t*) (size_t) 0xFFFABADA) *reloc_address += (size_t) page->address; else *reloc_address = 0; if (fread(&reloc_offset, sizeof(reloc_offset), 1, fh) != 1) { fclose(fh); yr_arena_destroy(new_arena); return ERROR_CORRUPT_FILE; } } fclose(fh); *arena = new_arena; return ERROR_SUCCESS; }
YR_AC_STATE* _yr_ac_create_state( YR_ARENA* arena, YR_AC_STATE* state, uint8_t input) { int result; YR_AC_STATE* new_state; YR_AC_LIST_BASED_STATE* list_based_state; YR_AC_TABLE_BASED_STATE* table_based_state; YR_AC_STATE_TRANSITION* new_transition; if (state->depth < MAX_TABLE_BASED_STATES_DEPTH) { result = yr_arena_allocate_struct( arena, sizeof(YR_AC_TABLE_BASED_STATE), (void**) &new_state, offsetof(YR_AC_TABLE_BASED_STATE, failure), offsetof(YR_AC_TABLE_BASED_STATE, matches), EOL); } else { result = yr_arena_allocate_struct( arena, sizeof(YR_AC_LIST_BASED_STATE), (void**) &new_state, offsetof(YR_AC_LIST_BASED_STATE, failure), offsetof(YR_AC_LIST_BASED_STATE, matches), offsetof(YR_AC_LIST_BASED_STATE, transitions), EOL); } if (result != ERROR_SUCCESS) return NULL; if (state->depth <= MAX_TABLE_BASED_STATES_DEPTH) { result = yr_arena_make_relocatable( arena, state, offsetof(YR_AC_TABLE_BASED_STATE, transitions[input]), EOL); if (result != ERROR_SUCCESS) return NULL; table_based_state = (YR_AC_TABLE_BASED_STATE*) state; table_based_state->transitions[input].state = new_state; } else { result = yr_arena_allocate_struct( arena, sizeof(YR_AC_STATE_TRANSITION), (void**) &new_transition, offsetof(YR_AC_STATE_TRANSITION, state), offsetof(YR_AC_STATE_TRANSITION, next), EOL); if (result != ERROR_SUCCESS) return NULL; list_based_state = (YR_AC_LIST_BASED_STATE*) state; new_transition->input = input; new_transition->state = new_state; new_transition->next = list_based_state->transitions; list_based_state->transitions = new_transition; } new_state->depth = state->depth + 1; return new_state; }
int yr_ac_compile( YR_AC_AUTOMATON* automaton, YR_ARENA* arena, YR_AC_TABLES* tables) { uint32_t i; FAIL_ON_ERROR(_yr_ac_create_failure_links(automaton)); FAIL_ON_ERROR(_yr_ac_optimize_failure_links(automaton)); FAIL_ON_ERROR(_yr_ac_build_transition_table(automaton)); FAIL_ON_ERROR(yr_arena_reserve_memory( arena, automaton->tables_size * sizeof(tables->transitions[0]) + automaton->tables_size * sizeof(tables->matches[0]))); FAIL_ON_ERROR(yr_arena_write_data( arena, automaton->t_table, sizeof(YR_AC_TRANSITION), (void**) &tables->transitions)); for (i = 1; i < automaton->tables_size; i++) { FAIL_ON_ERROR(yr_arena_write_data( arena, automaton->t_table + i, sizeof(YR_AC_TRANSITION), NULL)); } FAIL_ON_ERROR(yr_arena_write_data( arena, automaton->m_table, sizeof(YR_AC_MATCH_TABLE_ENTRY), (void**) &tables->matches)); FAIL_ON_ERROR(yr_arena_make_relocatable( arena, tables->matches, offsetof(YR_AC_MATCH_TABLE_ENTRY, match), EOL)); for (i = 1; i < automaton->tables_size; i++) { void* ptr; FAIL_ON_ERROR(yr_arena_write_data( arena, automaton->m_table + i, sizeof(YR_AC_MATCH_TABLE_ENTRY), (void**) &ptr)); FAIL_ON_ERROR(yr_arena_make_relocatable( arena, ptr, offsetof(YR_AC_MATCH_TABLE_ENTRY, match), EOL)); } return ERROR_SUCCESS; }