int yr_atoms_extract_from_re( YR_ATOMS_CONFIG* config, RE_AST* re_ast, int flags, YR_ATOM_LIST_ITEM** atoms, int* min_atom_quality) { YR_ATOM_TREE* atom_tree = (YR_ATOM_TREE*) yr_malloc(sizeof(YR_ATOM_TREE)); YR_ATOM_LIST_ITEM* wide_atoms; YR_ATOM_LIST_ITEM* case_insensitive_atoms; if (atom_tree == NULL) return ERROR_INSUFFICIENT_MEMORY; atom_tree->root_node = _yr_atoms_tree_node_create(ATOM_TREE_OR); if (atom_tree->root_node == NULL) { _yr_atoms_tree_destroy(atom_tree); return ERROR_INSUFFICIENT_MEMORY; } FAIL_ON_ERROR_WITH_CLEANUP( _yr_atoms_extract_from_re(config, re_ast, atom_tree->root_node), _yr_atoms_tree_destroy(atom_tree)); // Initialize atom list *atoms = NULL; // Choose the atoms that will be used. FAIL_ON_ERROR_WITH_CLEANUP( _yr_atoms_choose(config, atom_tree->root_node, atoms, min_atom_quality), _yr_atoms_tree_destroy(atom_tree)); _yr_atoms_tree_destroy(atom_tree); FAIL_ON_ERROR_WITH_CLEANUP( _yr_atoms_expand_wildcards(*atoms), { yr_atoms_list_destroy(*atoms); *atoms = NULL; });
static int _yr_atoms_choose( ATOM_TREE_NODE* node, YR_ATOM_LIST_ITEM** chosen_atoms, int* atoms_quality) { ATOM_TREE_NODE* child; YR_ATOM_LIST_ITEM* item; YR_ATOM_LIST_ITEM* tail; int i, quality; int max_quality = YR_MIN_ATOM_QUALITY; int min_quality = YR_MAX_ATOM_QUALITY; *chosen_atoms = NULL; switch (node->type) { case ATOM_TREE_LEAF: item = (YR_ATOM_LIST_ITEM*) yr_malloc(sizeof(YR_ATOM_LIST_ITEM)); if (item == NULL) return ERROR_INSUFFICIENT_MEMORY; for (i = 0; i < node->atom_length; i++) item->atom[i] = node->atom[i]; item->atom_length = node->atom_length; item->forward_code = node->forward_code; item->backward_code = node->backward_code; item->backtrack = 0; item->next = NULL; *chosen_atoms = item; *atoms_quality = _yr_atoms_quality(node->atom, node->atom_length); break; case ATOM_TREE_OR: child = node->children_head; while (child != NULL) { FAIL_ON_ERROR(_yr_atoms_choose(child, &item, &quality)); if (quality > max_quality) { max_quality = quality; yr_atoms_list_destroy(*chosen_atoms); *chosen_atoms = item; } else { yr_atoms_list_destroy(item); } child = child->next_sibling; } *atoms_quality = max_quality; break; case ATOM_TREE_AND: child = node->children_head; while (child != NULL) { FAIL_ON_ERROR(_yr_atoms_choose(child, &item, &quality)); if (quality < min_quality) min_quality = quality; if (item != NULL) { tail = item; while (tail->next != NULL) tail = tail->next; tail->next = *chosen_atoms; *chosen_atoms = item; } child = child->next_sibling; } *atoms_quality = min_quality; break; } return ERROR_SUCCESS; }
int yr_atoms_extract_from_re( RE_AST* re_ast, int flags, YR_ATOM_LIST_ITEM** atoms) { ATOM_TREE* atom_tree = (ATOM_TREE*) yr_malloc(sizeof(ATOM_TREE)); ATOM_TREE_NODE* temp; YR_ATOM_LIST_ITEM* wide_atoms; YR_ATOM_LIST_ITEM* case_insensitive_atoms; YR_ATOM_LIST_ITEM* triplet_atoms; int min_atom_quality = YR_MIN_ATOM_QUALITY; if (atom_tree == NULL) return ERROR_INSUFFICIENT_MEMORY; atom_tree->root_node = _yr_atoms_tree_node_create(ATOM_TREE_OR); if (atom_tree->root_node == NULL) { _yr_atoms_tree_destroy(atom_tree); return ERROR_INSUFFICIENT_MEMORY; } atom_tree->current_leaf = NULL; atom_tree->root_node = _yr_atoms_extract_from_re_node( re_ast->root_node, atom_tree, atom_tree->root_node); if (atom_tree->root_node == NULL) { _yr_atoms_tree_destroy(atom_tree); return ERROR_INSUFFICIENT_MEMORY; } if (atom_tree->current_leaf != NULL) _yr_atoms_tree_node_append(atom_tree->root_node, atom_tree->current_leaf); if (atom_tree->root_node->children_head == atom_tree->root_node->children_tail) { // The root OR node has a single child, there's no need for the OR node so // we proceed to destroy it and use its child as root. temp = atom_tree->root_node; atom_tree->root_node = atom_tree->root_node->children_head; yr_free(temp); } // Initialize atom list *atoms = NULL; if (atom_tree->root_node != NULL) { // Choose the atoms that will be used. FAIL_ON_ERROR_WITH_CLEANUP( _yr_atoms_choose(atom_tree->root_node, atoms, &min_atom_quality), _yr_atoms_tree_destroy(atom_tree)); } _yr_atoms_tree_destroy(atom_tree); if (min_atom_quality <= 2) { // Chosen atoms contain low quality ones, let's try infering some higher // quality atoms. FAIL_ON_ERROR_WITH_CLEANUP( yr_atoms_extract_triplets(re_ast->root_node, &triplet_atoms), { yr_atoms_list_destroy(*atoms); yr_atoms_list_destroy(triplet_atoms); *atoms = NULL; });
int yr_atoms_extract_from_re( RE* re, int flags, YR_ATOM_LIST_ITEM** atoms) { ATOM_TREE* atom_tree = yr_malloc(sizeof(ATOM_TREE)); ATOM_TREE_NODE* temp; YR_ATOM_LIST_ITEM* wide_atoms; YR_ATOM_LIST_ITEM* case_insentive_atoms; YR_ATOM_LIST_ITEM* triplet_atoms; int min_atom_quality = 0; atom_tree->root_node = _yr_atoms_tree_node_create(ATOM_TREE_OR);; atom_tree->current_leaf = NULL; atom_tree->root_node = _yr_atoms_extract_from_re_node( re->root_node, atom_tree, atom_tree->root_node); if (atom_tree->current_leaf != NULL) _yr_atoms_tree_node_append(atom_tree->root_node, atom_tree->current_leaf); if (atom_tree->root_node->children_head == atom_tree->root_node->children_tail) { // The root OR node has a single child, there's no need for the OR node so // we proceed to destroy it and use its child as root. temp = atom_tree->root_node; atom_tree->root_node = atom_tree->root_node->children_head; yr_free(temp); } // Choose the atoms that will be used. min_atom_quality = _yr_atoms_choose(atom_tree->root_node, atoms); _yr_atoms_tree_destroy(atom_tree); if (min_atom_quality <= 2) { // Choosen atoms contain low quality ones, let's try infering some higher // quality atoms. yr_atoms_extract_triplets(re->root_node, &triplet_atoms); if (min_atom_quality < _yr_atoms_min_quality(triplet_atoms)) { yr_atoms_list_destroy(*atoms); *atoms = triplet_atoms; } else { yr_atoms_list_destroy(triplet_atoms); } } if (flags & STRING_GFLAGS_WIDE) { FAIL_ON_ERROR(_yr_atoms_wide( *atoms, &wide_atoms)); if (flags & STRING_GFLAGS_ASCII) { *atoms = _yr_atoms_list_concat(*atoms, wide_atoms); } else { yr_atoms_list_destroy(*atoms); *atoms = wide_atoms; } } if (flags & STRING_GFLAGS_NO_CASE) { FAIL_ON_ERROR(_yr_atoms_case_insentive( *atoms, &case_insentive_atoms)); *atoms = _yr_atoms_list_concat(*atoms, case_insentive_atoms); } return ERROR_SUCCESS; }
int _yr_atoms_choose( ATOM_TREE_NODE* node, YR_ATOM_LIST_ITEM** choosen_atoms) { ATOM_TREE_NODE* child; YR_ATOM_LIST_ITEM* item; YR_ATOM_LIST_ITEM* tail; int i, quality; int max_quality = 0; int min_quality = 10000; *choosen_atoms = NULL; if (node == NULL) return 0; switch (node->type) { case ATOM_TREE_LEAF: item = yr_malloc(sizeof(YR_ATOM_LIST_ITEM)); for (i = 0; i < node->atom_length; i++) item->atom[i] = node->atom[i]; item->atom_length = node->atom_length; item->forward_code = node->forward_code; item->backward_code = node->backward_code; item->backtrack = 0; item->next = NULL; *choosen_atoms = item; return _yr_atoms_quality(node->atom, node->atom_length); case ATOM_TREE_OR: child = node->children_head; while (child != NULL) { quality = _yr_atoms_choose(child, &item); if (quality > max_quality) { max_quality = quality; yr_atoms_list_destroy(*choosen_atoms); *choosen_atoms = item; } else { yr_atoms_list_destroy(item); } child = child->next_sibling; } return max_quality; case ATOM_TREE_AND: child = node->children_head; while (child != NULL) { quality = _yr_atoms_choose(child, &item); if (quality < min_quality) min_quality = quality; tail = item; while (tail->next != NULL) tail = tail->next; tail->next = *choosen_atoms; *choosen_atoms = item; child = child->next_sibling; } return min_quality; } return 0; }
static int _yr_atoms_choose( YR_ATOMS_CONFIG* config, YR_ATOM_TREE_NODE* node, YR_ATOM_LIST_ITEM** chosen_atoms, int* atoms_quality) { YR_ATOM_TREE_NODE* child; YR_ATOM_LIST_ITEM* item; YR_ATOM_LIST_ITEM* tail; int shift, quality; int max_quality = YR_MIN_ATOM_QUALITY; int min_quality = YR_MAX_ATOM_QUALITY; *chosen_atoms = NULL; *atoms_quality = YR_MIN_ATOM_QUALITY; switch (node->type) { case ATOM_TREE_LEAF: item = (YR_ATOM_LIST_ITEM*) yr_malloc(sizeof(YR_ATOM_LIST_ITEM)); if (item == NULL) return ERROR_INSUFFICIENT_MEMORY; memcpy(&item->atom, &node->atom, sizeof(YR_ATOM)); shift = _yr_atoms_trim(&item->atom); if (item->atom.length > 0) { item->forward_code = node->re_nodes[shift]->forward_code; item->backward_code = node->re_nodes[shift]->backward_code; item->backtrack = 0; item->next = NULL; *chosen_atoms = item; *atoms_quality = config->get_atom_quality(config, &item->atom); } else { yr_free(item); } break; case ATOM_TREE_OR: // The choosen nodes are those coming from the highest quality child. child = node->children_head; while (child != NULL) { FAIL_ON_ERROR(_yr_atoms_choose(config, child, &item, &quality)); if (quality > max_quality) { max_quality = quality; yr_atoms_list_destroy(*chosen_atoms); *chosen_atoms = item; } else { yr_atoms_list_destroy(item); } if (max_quality == YR_MAX_ATOM_QUALITY) break; child = child->next_sibling; } *atoms_quality = max_quality; break; case ATOM_TREE_AND: // The choosen nodes are the concatenation of the the nodes choosen from // all the children. child = node->children_head; while (child != NULL) { FAIL_ON_ERROR(_yr_atoms_choose(config, child, &item, &quality)); if (quality < min_quality) min_quality = quality; if (item != NULL) { tail = item; while (tail->next != NULL) tail = tail->next; tail->next = *chosen_atoms; *chosen_atoms = item; } child = child->next_sibling; } *atoms_quality = min_quality; break; } return ERROR_SUCCESS; }