int yr_atoms_min_quality( YR_ATOM_LIST_ITEM* atom_list) { YR_ATOM_LIST_ITEM* atom; int quality; int min_quality = YR_MAX_ATOM_QUALITY; if (atom_list == NULL) return YR_MIN_ATOM_QUALITY; atom = atom_list; while (atom != NULL) { quality = _yr_atoms_quality(atom->atom, atom->atom_length); if (quality < min_quality) min_quality = quality; atom = atom->next; } return min_quality; }
int _yr_atoms_min_quality( YR_ATOM_LIST_ITEM* atom_list) { YR_ATOM_LIST_ITEM* atom; int quality; int min_quality = 100000; if (atom_list == NULL) return 0; atom = atom_list; while (atom != NULL) { quality = _yr_atoms_quality(atom->atom, atom->atom_length); if (quality < min_quality) min_quality = quality; atom = atom->next; } return min_quality; }
static ATOM_TREE_NODE* _yr_atoms_extract_from_re_node( RE_NODE* re_node, ATOM_TREE* atom_tree, ATOM_TREE_NODE* current_node) { ATOM_TREE_NODE* left_node; ATOM_TREE_NODE* right_node; ATOM_TREE_NODE* and_node; ATOM_TREE_NODE* current_leaf; ATOM_TREE_NODE* temp; int quality; int new_quality; int i; uint8_t new_atom[MAX_ATOM_LENGTH]; switch(re_node->type) { case RE_NODE_LITERAL: if (atom_tree->current_leaf == NULL) { atom_tree->current_leaf = _yr_atoms_tree_node_create(ATOM_TREE_LEAF); if (atom_tree->current_leaf == NULL) return NULL; atom_tree->current_leaf->forward_code = re_node->forward_code; atom_tree->current_leaf->backward_code = re_node->backward_code; assert(atom_tree->current_leaf->forward_code != NULL); assert(atom_tree->current_leaf->backward_code != NULL); } current_leaf = atom_tree->current_leaf; if (current_leaf->atom_length < MAX_ATOM_LENGTH) { current_leaf->atom[current_leaf->atom_length] = (uint8_t) re_node->value; current_leaf->recent_nodes[current_leaf->atom_length] = re_node; current_leaf->atom_length++; } else { for (i = 1; i < MAX_ATOM_LENGTH; i++) current_leaf->recent_nodes[i - 1] = current_leaf->recent_nodes[i]; current_leaf->recent_nodes[MAX_ATOM_LENGTH - 1] = re_node; for (i = 0; i < MAX_ATOM_LENGTH; i++) new_atom[i] = (uint8_t) current_leaf->recent_nodes[i]->value; quality = _yr_atoms_quality( current_leaf->atom, MAX_ATOM_LENGTH); new_quality = _yr_atoms_quality( new_atom, MAX_ATOM_LENGTH); if (new_quality > quality) { for (i = 0; i < MAX_ATOM_LENGTH; i++) current_leaf->atom[i] = new_atom[i]; current_leaf->forward_code = \ current_leaf->recent_nodes[0]->forward_code; current_leaf->backward_code = \ current_leaf->recent_nodes[0]->backward_code; assert(current_leaf->forward_code != NULL); assert(current_leaf->backward_code != NULL); } } return current_node; case RE_NODE_CONCAT: current_node = _yr_atoms_extract_from_re_node( re_node->left, atom_tree, current_node); if (current_node == NULL) return NULL; current_node = _yr_atoms_extract_from_re_node( re_node->right, atom_tree, current_node); return current_node; case RE_NODE_ALT: append_current_leaf_to_node(current_node); left_node = _yr_atoms_tree_node_create(ATOM_TREE_OR); if (left_node == NULL) return NULL; left_node = _yr_atoms_extract_from_re_node( re_node->left, atom_tree, left_node); if (left_node == NULL) return NULL; append_current_leaf_to_node(left_node); if (left_node->children_head == NULL) { _yr_atoms_tree_node_destroy(left_node); return current_node; } if (left_node->children_head == left_node->children_tail) { temp = left_node; left_node = left_node->children_head; yr_free(temp); } right_node = _yr_atoms_tree_node_create(ATOM_TREE_OR); if (right_node == NULL) return NULL; right_node = _yr_atoms_extract_from_re_node( re_node->right, atom_tree, right_node); if (right_node == NULL) return NULL; append_current_leaf_to_node(right_node); if (right_node->children_head == NULL) { _yr_atoms_tree_node_destroy(left_node); _yr_atoms_tree_node_destroy(right_node); return current_node; } if (right_node->children_head == right_node->children_tail) { temp = right_node; right_node = right_node->children_head; yr_free(temp); } and_node = _yr_atoms_tree_node_create(ATOM_TREE_AND); if (and_node == NULL) return NULL; and_node->children_head = left_node; and_node->children_tail = right_node; left_node->next_sibling = right_node; _yr_atoms_tree_node_append(current_node, and_node); return current_node; case RE_NODE_RANGE: if (re_node->start == 0) append_current_leaf_to_node(current_node); for (i = 0; i < re_node->start; i++) { current_node = _yr_atoms_extract_from_re_node( re_node->left, atom_tree, current_node); if (current_node == NULL) return NULL; } if (re_node->start != re_node->end) append_current_leaf_to_node(current_node); return current_node; case RE_NODE_PLUS: current_node = _yr_atoms_extract_from_re_node( re_node->left, atom_tree, current_node); if (current_node == NULL) return NULL; append_current_leaf_to_node(current_node); return current_node; case RE_NODE_ANY: case RE_NODE_RANGE_ANY: case RE_NODE_STAR: case RE_NODE_CLASS: case RE_NODE_MASKED_LITERAL: case RE_NODE_WORD_CHAR: case RE_NODE_NON_WORD_CHAR: case RE_NODE_SPACE: case RE_NODE_NON_SPACE: case RE_NODE_DIGIT: case RE_NODE_NON_DIGIT: case RE_NODE_EMPTY: case RE_NODE_ANCHOR_START: case RE_NODE_ANCHOR_END: case RE_NODE_WORD_BOUNDARY: case RE_NODE_NON_WORD_BOUNDARY: append_current_leaf_to_node(current_node); return current_node; default: assert(FALSE); } return 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_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; }
int yr_atoms_extract_from_string( uint8_t* string, int string_length, int flags, YR_ATOM_LIST_ITEM** atoms) { YR_ATOM_LIST_ITEM* item; YR_ATOM_LIST_ITEM* case_insentive_atoms; YR_ATOM_LIST_ITEM* wide_atoms; int max_quality; int quality; int i, j, length; item = yr_malloc(sizeof(YR_ATOM_LIST_ITEM)); if (item == NULL) return ERROR_INSUFICIENT_MEMORY; item->forward_code = NULL; item->backward_code = NULL; item->next = NULL; item->backtrack = 0; length = min(string_length, MAX_ATOM_LENGTH); for (i = 0; i < length; i++) item->atom[i] = string[i]; item->atom_length = i; max_quality = _yr_atoms_quality(string, length); for (i = MAX_ATOM_LENGTH; i < string_length; i++) { quality = _yr_atoms_quality( string + i - MAX_ATOM_LENGTH + 1, MAX_ATOM_LENGTH); if (quality > max_quality) { for (j = 0; j < MAX_ATOM_LENGTH; j++) item->atom[j] = string[i + j - MAX_ATOM_LENGTH + 1]; item->backtrack = i - MAX_ATOM_LENGTH + 1; max_quality = quality; } } if (flags & STRING_GFLAGS_WIDE) { FAIL_ON_ERROR(_yr_atoms_wide( item, &wide_atoms)); if (flags & STRING_GFLAGS_ASCII) { item = _yr_atoms_list_concat(item, wide_atoms); } else { yr_atoms_list_destroy(item); item = wide_atoms; } } if (flags & STRING_GFLAGS_NO_CASE) { FAIL_ON_ERROR(_yr_atoms_case_insentive( item, &case_insentive_atoms)); item = _yr_atoms_list_concat(item, case_insentive_atoms); } *atoms = item; return ERROR_SUCCESS; }