YR_API int yr_compiler_create( YR_COMPILER** compiler) { int result; YR_COMPILER* new_compiler; new_compiler = (YR_COMPILER*) yr_calloc(1, sizeof(YR_COMPILER)); if (new_compiler == NULL) return ERROR_INSUFICIENT_MEMORY; new_compiler->errors = 0; new_compiler->callback = NULL; new_compiler->last_error = ERROR_SUCCESS; new_compiler->last_error_line = 0; new_compiler->error_line = 0; new_compiler->last_result = ERROR_SUCCESS; new_compiler->file_stack_ptr = 0; new_compiler->file_name_stack_ptr = 0; new_compiler->fixup_stack_head = NULL; new_compiler->allow_includes = 1; new_compiler->loop_depth = 0; new_compiler->loop_for_of_mem_offset = -1; new_compiler->compiled_rules_arena = NULL; new_compiler->namespaces_count = 0; new_compiler->current_rule = NULL; result = yr_hash_table_create(10007, &new_compiler->rules_table); if (result == ERROR_SUCCESS) result = yr_hash_table_create(10007, &new_compiler->objects_table); if (result == ERROR_SUCCESS) result = yr_hash_table_create(101, &new_compiler->strings_table); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->sz_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->rules_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->strings_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->code_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->re_code_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->externals_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->namespaces_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->metas_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->automaton_arena); if (result == ERROR_SUCCESS) result = yr_arena_create(65536, 0, &new_compiler->matches_arena); if (result == ERROR_SUCCESS) result = yr_ac_automaton_create(&new_compiler->automaton); if (result == ERROR_SUCCESS) { *compiler = new_compiler; } else // if error, do cleanup { yr_compiler_destroy(new_compiler); } return result; }
static int _yr_ac_build_transition_table( YR_AC_AUTOMATON* automaton) { YR_AC_STATE* state; YR_AC_STATE* child_state; YR_AC_STATE* root_state = automaton->root; uint32_t slot; QUEUE queue = { NULL, NULL}; automaton->tables_size = 1024; automaton->t_table = (YR_AC_TRANSITION_TABLE) yr_calloc( automaton->tables_size, sizeof(YR_AC_TRANSITION)); automaton->m_table = (YR_AC_MATCH_TABLE) yr_calloc( automaton->tables_size, sizeof(YR_AC_MATCH_TABLE_ENTRY)); automaton->bitmask = (YR_BITMASK*) yr_calloc( YR_BITMASK_SIZE(automaton->tables_size), sizeof(YR_BITMASK)); if (automaton->t_table == NULL || automaton->m_table == NULL || automaton->bitmask == NULL) { yr_free(automaton->t_table); yr_free(automaton->m_table); yr_free(automaton->bitmask); return ERROR_INSUFFICIENT_MEMORY; } automaton->t_table[0] = YR_AC_MAKE_TRANSITION(0, 0); automaton->m_table[0].match = root_state->matches; yr_bitmask_set(automaton->bitmask, 0); // Index 0 is for root node. Unused indexes start at 1. automaton->t_table_unused_candidate = 1; child_state = root_state->first_child; while (child_state != NULL) { child_state->t_table_slot = child_state->input + 1; automaton->t_table[child_state->input + 1] = YR_AC_MAKE_TRANSITION( 0, child_state->input + 1); yr_bitmask_set(automaton->bitmask, child_state->input + 1); FAIL_ON_ERROR(_yr_ac_queue_push(&queue, child_state)); child_state = child_state->siblings; } while (!_yr_ac_queue_is_empty(&queue)) { state = _yr_ac_queue_pop(&queue); FAIL_ON_ERROR(_yr_ac_find_suitable_transition_table_slot( automaton, state, &slot)); automaton->t_table[state->t_table_slot] |= (slot << YR_AC_SLOT_OFFSET_BITS); state->t_table_slot = slot; automaton->t_table[slot] = YR_AC_MAKE_TRANSITION( state->failure->t_table_slot, 0); yr_bitmask_set(automaton->bitmask, slot); automaton->m_table[slot].match = state->matches; // Push childrens of current_state child_state = state->first_child; while (child_state != NULL) { child_state->t_table_slot = slot + child_state->input + 1; automaton->t_table[child_state->t_table_slot] = YR_AC_MAKE_TRANSITION( 0, child_state->input + 1); yr_bitmask_set(automaton->bitmask, child_state->t_table_slot); FAIL_ON_ERROR(_yr_ac_queue_push(&queue, child_state)); child_state = child_state->siblings; } } return ERROR_SUCCESS; }