int yr_scan_verify_match( YR_SCAN_CONTEXT* context, YR_AC_MATCH* ac_match, const uint8_t* data, size_t data_size, uint64_t data_base, size_t offset) { YR_STRING* string = ac_match->string; int result; if (data_size - offset <= 0) return ERROR_SUCCESS; if (STRING_IS_DISABLED(string)) return ERROR_SUCCESS; if (context->flags & SCAN_FLAGS_FAST_MODE && STRING_IS_SINGLE_MATCH(string) && string->matches[context->tidx].head != NULL) return ERROR_SUCCESS; if (STRING_IS_FIXED_OFFSET(string) && string->fixed_offset != data_base + offset) return ERROR_SUCCESS; #ifdef PROFILING_ENABLED uint64_t start_time = yr_stopwatch_elapsed_us(&context->stopwatch); #endif if (STRING_IS_LITERAL(string)) { result = _yr_scan_verify_literal_match( context, ac_match, data, data_size, data_base, offset); } else { result = _yr_scan_verify_re_match( context, ac_match, data, data_size, data_base, offset); } if (result != ERROR_SUCCESS) context->last_error_string = string; #ifdef PROFILING_ENABLED uint64_t finish_time = yr_stopwatch_elapsed_us(&context->stopwatch); #ifdef _WIN32 InterlockedAdd64(&string->time_cost, finish_time - start_time); InterlockedAdd64(&string->rule->time_cost, finish_time - start_time); #else __sync_fetch_and_add(&string->time_cost, finish_time - start_time); __sync_fetch_and_add(&string->rule->time_cost, finish_time - start_time); #endif #endif return result; }
int yr_scan_verify_match( YR_AC_MATCH* ac_match, uint8_t* data, size_t data_size, size_t data_base, size_t offset, YR_ARENA* matches_arena, int flags) { YR_STRING* string = ac_match->string; #ifdef PROFILING_ENABLED clock_t start = clock(); #endif if (data_size - offset <= 0) return ERROR_SUCCESS; if (flags & SCAN_FLAGS_FAST_MODE && STRING_IS_SINGLE_MATCH(string) && STRING_FOUND(string)) return ERROR_SUCCESS; if (STRING_IS_FIXED_OFFSET(string) && string->fixed_offset != data_base + offset) return ERROR_SUCCESS; if (STRING_IS_LITERAL(string)) { FAIL_ON_ERROR(_yr_scan_verify_literal_match( ac_match, data, data_size, data_base, offset, matches_arena)); } else { FAIL_ON_ERROR(_yr_scan_verify_re_match( ac_match, data, data_size, data_base, offset, matches_arena)); } #ifdef PROFILING_ENABLED string->clock_ticks += clock() - start; #endif return ERROR_SUCCESS; }
int yr_scan_verify_match( YR_SCAN_CONTEXT* context, YR_AC_MATCH* ac_match, uint8_t* data, size_t data_size, size_t data_base, size_t offset) { YR_STRING* string = ac_match->string; #ifdef PROFILING_ENABLED clock_t start = clock(); #endif if (data_size - offset <= 0) return ERROR_SUCCESS; if (context->flags & SCAN_FLAGS_FAST_MODE && STRING_IS_SINGLE_MATCH(string) && string->matches[context->tidx].head != NULL) return ERROR_SUCCESS; if (STRING_IS_FIXED_OFFSET(string) && string->fixed_offset != data_base + offset) return ERROR_SUCCESS; if (STRING_IS_LITERAL(string)) { FAIL_ON_ERROR(_yr_scan_verify_literal_match( context, ac_match, data, data_size, data_base, offset)); } else { FAIL_ON_ERROR(_yr_scan_verify_re_match( context, ac_match, data, data_size, data_base, offset)); } #ifdef PROFILING_ENABLED string->clock_ticks += clock() - start; #endif return ERROR_SUCCESS; }
inline int _yr_scan_verify_match( YR_AC_MATCH* ac_match, uint8_t* data, size_t data_size, size_t offset, YR_ARENA* matches_arena, int fast_scan_mode) { YR_STRING* string = ac_match->string; #ifdef PROFILING_ENABLED clock_t start = clock(); #endif if (data_size - offset <= 0) return ERROR_SUCCESS; if (fast_scan_mode && STRING_IS_SINGLE_MATCH(string) && STRING_FOUND(string)) return ERROR_SUCCESS; if (STRING_IS_LITERAL(string)) { FAIL_ON_ERROR(_yr_scan_verify_literal_match( ac_match, data, data_size, offset, matches_arena)); } else { FAIL_ON_ERROR(_yr_scan_verify_re_match( ac_match, data, data_size, offset, matches_arena)); } #ifdef PROFILING_ENABLED string->clock_ticks += clock() - start; #endif return ERROR_SUCCESS; }
YR_STRING* yr_parser_reduce_string_declaration( yyscan_t yyscanner, int32_t flags, const char* identifier, SIZED_STRING* str) { int i; int error_offset; int min_atom_length; char* file_name; char message[512]; YR_STRING* string; YR_AC_MATCH* new_match; ATOM_TREE* atom_tree; YR_ATOM_LIST_ITEM* atom; YR_ATOM_LIST_ITEM* atom_list = NULL; RE* re = NULL; uint8_t* literal_string; int literal_string_len; int max_string_len; YR_COMPILER* compiler = yyget_extra(yyscanner); compiler->last_result = yr_arena_allocate_struct( compiler->strings_arena, sizeof(YR_STRING), (void**) &string, offsetof(YR_STRING, identifier), offsetof(YR_STRING, string), EOL); if (compiler->last_result != ERROR_SUCCESS) return NULL; compiler->last_result = yr_arena_write_string( compiler->sz_arena, identifier, &string->identifier); if (compiler->last_result != ERROR_SUCCESS) return NULL; if (strcmp(identifier,"$") == 0) flags |= STRING_GFLAGS_ANONYMOUS; if (!(flags & STRING_GFLAGS_WIDE)) flags |= STRING_GFLAGS_ASCII; // The STRING_GFLAGS_SINGLE_MATCH flag indicates that finding // a single match for the string is enough. This is true in // most cases, except when the string count (#) and string offset (@) // operators are used. All strings are marked STRING_FLAGS_SINGLE_MATCH // initially, and unmarked later if required. flags |= STRING_GFLAGS_SINGLE_MATCH; string->g_flags = flags; memset(string->matches, 0, sizeof(string->matches)); if (flags & STRING_GFLAGS_HEXADECIMAL || flags & STRING_GFLAGS_REGEXP) { if (flags & STRING_GFLAGS_HEXADECIMAL) compiler->last_result = yr_re_compile_hex( str->c_string, &re); else compiler->last_result = yr_re_compile( str->c_string, &re); if (compiler->last_result != ERROR_SUCCESS) { snprintf( message, sizeof(message), "invalid %s in string \"%s\": %s", (flags & STRING_GFLAGS_HEXADECIMAL) ? "hex string" : "regular expression", identifier, re->error_message); yr_compiler_set_error_extra_info(compiler, message); string = NULL; goto _exit; } if (re->flags & RE_FLAGS_START_ANCHORED) string->g_flags |= STRING_GFLAGS_START_ANCHORED; if (re->flags & RE_FLAGS_END_ANCHORED) string->g_flags |= STRING_GFLAGS_END_ANCHORED; if (re->flags & RE_FLAGS_FAST_HEX_REGEXP) string->g_flags |= STRING_GFLAGS_FAST_HEX_REGEXP; if (re->flags & RE_FLAGS_LITERAL_STRING) { string->g_flags |= STRING_GFLAGS_LITERAL; literal_string = re->literal_string; literal_string_len = re->literal_string_len; compiler->last_result = yr_atoms_extract_from_string( literal_string, literal_string_len, string->g_flags, &atom_list); } else { compiler->last_result = yr_re_emit_code( re, compiler->re_code_arena); if (compiler->last_result != ERROR_SUCCESS) { string = NULL; goto _exit; } compiler->last_result = yr_atoms_extract_from_re( re, string->g_flags, &atom_list); } } else { string->g_flags |= STRING_GFLAGS_LITERAL; literal_string = (uint8_t*) str->c_string; literal_string_len = str->length; compiler->last_result = yr_atoms_extract_from_string( literal_string, literal_string_len, string->g_flags, &atom_list); } if (compiler->last_result != ERROR_SUCCESS) { string = NULL; goto _exit; } if (STRING_IS_LITERAL(string)) { compiler->last_result = yr_arena_write_data( compiler->sz_arena, literal_string, literal_string_len, (void*) &string->string); if (compiler->last_result != ERROR_SUCCESS) { string = NULL; goto _exit; } string->length = literal_string_len; } // Add the string to Aho-Corasick automaton. if (atom_list != NULL) { compiler->last_result = yr_ac_add_string( compiler->automaton_arena, compiler->automaton, string, atom_list); } else { compiler->last_result = yr_arena_allocate_struct( compiler->automaton_arena, sizeof(YR_AC_MATCH), (void**) &new_match, offsetof(YR_AC_MATCH, string), offsetof(YR_AC_MATCH, forward_code), offsetof(YR_AC_MATCH, backward_code), offsetof(YR_AC_MATCH, next), EOL); if (compiler->last_result == ERROR_SUCCESS) { new_match->backtrack = 0; new_match->string = string; new_match->forward_code = re->root_node->forward_code; new_match->backward_code = NULL; new_match->next = compiler->automaton->root->matches; compiler->automaton->root->matches = new_match; } } atom = atom_list; if (atom != NULL) min_atom_length = MAX_ATOM_LENGTH; else min_atom_length = 0; while (atom != NULL) { if (atom->atom_length < min_atom_length) min_atom_length = atom->atom_length; atom = atom->next; } if (STRING_IS_LITERAL(string)) { if (STRING_IS_WIDE(string)) max_string_len = string->length * 2; else max_string_len = string->length; if (max_string_len == min_atom_length) string->g_flags |= STRING_GFLAGS_FITS_IN_ATOM; } if (compiler->file_name_stack_ptr > 0) file_name = compiler->file_name_stack[compiler->file_name_stack_ptr - 1]; else file_name = NULL; if (min_atom_length < 2 && compiler->error_report_function != NULL) { snprintf( message, sizeof(message), "%s is slowing down scanning%s", string->identifier, min_atom_length == 0 ? " (critical!)" : ""); compiler->error_report_function( YARA_ERROR_LEVEL_WARNING, file_name, yyget_lineno(yyscanner), message); } if (compiler->last_result != ERROR_SUCCESS) string = NULL; _exit: if (atom_list != NULL) yr_atoms_list_destroy(atom_list); if (re != NULL) yr_re_destroy(re); return string; }